Advertisement
Guest User

Untitled

a guest
Jun 20th, 2019
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 20.87 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. from os import environ
  4. from os.path import exists as path_exists, join as path_join, isfile, isdir, abspath
  5. from sys import exit
  6.  
  7.  
  8. class MonoBuildError(Exception):
  9. '''Generic exception for custom build errors'''
  10. def __init__(self, msg):
  11. super(MonoBuildError, self).__init__(msg)
  12. self.message = msg
  13.  
  14.  
  15. def run_command(command, args=[], custom_env=None, name='command'):
  16. def cmd_args_as_text(cmd_args):
  17. return ' '.join([arg if not ' ' in arg else '"%s"' % arg for arg in cmd_args])
  18.  
  19. assert isinstance(command, str) and isinstance(args, list)
  20. args = [command] + args
  21.  
  22. import subprocess
  23. try:
  24. print('Running command \'%s\': %s' % (name, cmd_args_as_text(args)))
  25. if custom_env is None:
  26. subprocess.check_call(args)
  27. else:
  28. subprocess.check_call(args, env=custom_env)
  29. print('Command \'%s\' completed successfully' % name)
  30. except subprocess.CalledProcessError as e:
  31. raise MonoBuildError('\'%s\' exited with error code: %s' % (name, e.returncode))
  32.  
  33.  
  34. # Creates the directory if no other file or directory with the same path exists
  35. def mkdir_p(path):
  36. from os import makedirs
  37. if not path_exists(path):
  38. print('creating directory: ' + path)
  39. makedirs(path)
  40.  
  41.  
  42. def chdir(path):
  43. from os import chdir as os_chdir
  44. print('entering directory: ' + path)
  45. os_chdir(path)
  46.  
  47.  
  48. # Remove files and/or directories recursively
  49. def rm_rf(*paths):
  50. from os import remove
  51. from shutil import rmtree
  52. for path in paths:
  53. if isfile(path):
  54. print('removing file: ' + path)
  55. remove(path)
  56. elif isdir(path):
  57. print('removing directory and its contents: ' + path)
  58. rmtree(path)
  59.  
  60.  
  61. def globs(pathnames, dirpath='.'):
  62. import glob
  63. files = []
  64. for pathname in pathnames:
  65. files.extend(glob.glob(path_join(dirpath, pathname)))
  66. return files
  67.  
  68.  
  69. TOOLCHAIN_NAME_FMT = '%s-api%s-clang'
  70.  
  71. CONFIGURATION = None
  72. RELEASE = None
  73.  
  74. ANDROID_TOOLCHAINS_PREFIX = None
  75.  
  76. ANDROID_SDK_ROOT = None
  77. ANDROID_NDK_ROOT = None
  78.  
  79. ENABLE_CXX = None
  80. VERBOSE_MAKE = None
  81. STRIP_LIBS = None
  82.  
  83. CONFIGURE_DIR = None
  84. INSTALL_DIR = None
  85.  
  86. MONO_SOURCE_ROOT = None
  87.  
  88. _ANDROID_API_VERSION = None
  89. _ANDROID_CMAKE_VERSION = None
  90.  
  91.  
  92. class AndroidTargetInfo:
  93. archs = {
  94. 'armeabi-v7a': 'arm',
  95. 'arm64-v8a': 'arm64',
  96. 'x86': 'x86',
  97. 'x86_64': 'x86_64'
  98. }
  99.  
  100. abi_names = {
  101. 'armeabi-v7a': 'arm-linux-androideabi',
  102. 'arm64-v8a': 'aarch64-linux-android',
  103. 'x86': 'i686-linux-android',
  104. 'x86_64': 'x86_64-linux-android'
  105. }
  106.  
  107. host_triples = {
  108. 'armeabi-v7a': 'armv5-linux-androideabi',
  109. 'arm64-v8a': 'aarch64-linux-android',
  110. 'x86': 'i686-linux-android',
  111. 'x86_64': 'x86_64-linux-android'
  112. }
  113.  
  114.  
  115. def android_autodetect_cmake():
  116. from distutils.version import StrictVersion
  117. from os import listdir
  118.  
  119. sdk_cmake_basedir = path_join(ANDROID_SDK_ROOT, 'cmake')
  120. versions = []
  121.  
  122. for entry in listdir(sdk_cmake_basedir):
  123. if isdir(path_join(sdk_cmake_basedir, entry)):
  124. try:
  125. version = StrictVersion(entry)
  126. versions += [version]
  127. except ValueError:
  128. continue # Not a version folder
  129.  
  130. if len(versions) == 0:
  131. raise MonoBuildError('Cannot auto-detect Android CMake version')
  132.  
  133. lattest_version = str(sorted(versions)[-1])
  134. print('Auto-detected Android CMake version: ' + lattest_version)
  135.  
  136. return lattest_version
  137.  
  138.  
  139. def get_api_version_or_min(target):
  140. min_versions = { 'arm64-v8a': '21', 'x86_64': '21' }
  141. if target in min_versions and int(_ANDROID_API_VERSION) < int(min_versions[target]):
  142. print('WARNING: %s is less than minimum platform for %s; using %s' % (_ANDROID_API_VERSION, target, min_versions[target]))
  143. return min_versions[target]
  144. return _ANDROID_API_VERSION
  145.  
  146.  
  147. def get_android_cmake_version():
  148. return _ANDROID_CMAKE_VERSION if _ANDROID_CMAKE_VERSION != 'autodetect' else android_autodetect_cmake()
  149.  
  150.  
  151. def setup_runtime_template(env, product, target, host_triple):
  152. BITNESS = ''
  153. if any(s in host_triple for s in ['i686', 'i386']):
  154. BITNESS = '-m32'
  155. elif 'x86_64' in host_triple:
  156. BITNESS = '-m64'
  157.  
  158. CFLAGS = []
  159. CFLAGS += ['-O2', '-g'] if RELEASE else ['-O0', '-ggdb3', '-fno-omit-frame-pointer']
  160. CFLAGS += env.get('_%s-%s_CFLAGS' % (product, target), [])
  161. CFLAGS += env.get('%s-%s_CFLAGS' % (product, target), [])
  162. CFLAGS += [BITNESS] if BITNESS else []
  163.  
  164. CXXFLAGS = []
  165. CXXFLAGS += ['-O2', '-g'] if RELEASE else ['-O0', '-ggdb3', '-fno-omit-frame-pointer']
  166. CXXFLAGS += env.get('_%s-%s_CXXFLAGS' % (product, target), [])
  167. CXXFLAGS += env.get('%s-%s_CXXFLAGS' % (product, target), [])
  168. CXXFLAGS += [BITNESS] if BITNESS else []
  169.  
  170. CPPFLAGS = []
  171. CPPFLAGS += ['-O2', '-g'] if RELEASE else ['-O0', '-ggdb3', '-fno-omit-frame-pointer']
  172. CPPFLAGS += env.get('_%s-%s_CPPFLAGS' % (product, target), [])
  173. CPPFLAGS += env.get('%s-%s_CPPFLAGS' % (product, target), [])
  174. CPPFLAGS += [BITNESS] if BITNESS else []
  175.  
  176. CXXCPPFLAGS = []
  177. CXXCPPFLAGS += ['-O2', '-g'] if RELEASE else ['-O0', '-ggdb3', '-fno-omit-frame-pointer']
  178. CXXCPPFLAGS += env.get('_%s-%s_CXXCPPFLAGS' % (product, target), [])
  179. CXXCPPFLAGS += env.get('%s-%s_CXXCPPFLAGS' % (product, target), [])
  180. CXXCPPFLAGS += [BITNESS] if BITNESS else []
  181.  
  182. LDFLAGS = []
  183. LDFLAGS += env.get('_%s-%s_LDFLAGS' % (product, target), [])
  184. LDFLAGS += env.get('%s-%s_LDFLAGS' % (product, target), [])
  185.  
  186. AC_VARS = []
  187. AC_VARS += env.get('_%s-%s_AC_VARS' % (product, target), [])
  188. AC_VARS += env.get('%s-%s_AC_VARS' % (product, target), [])
  189.  
  190. CONFIGURE_ENVIRONMENT = {}
  191.  
  192. def append_product_env_var(var_name):
  193. val = env.get('_%s-%s_%s' % (product, target, var_name), '')
  194. if val:
  195. CONFIGURE_ENVIRONMENT[var_name] = val
  196.  
  197. append_product_env_var('AR')
  198. append_product_env_var('AS')
  199. append_product_env_var('CC')
  200. append_product_env_var('CPP')
  201. append_product_env_var('CXX')
  202. append_product_env_var('CXXCPP')
  203. append_product_env_var('DLLTOOL')
  204. append_product_env_var('LD')
  205. append_product_env_var('OBJDUMP')
  206. append_product_env_var('RANLIB')
  207. append_product_env_var('CMAKE')
  208. append_product_env_var('STRIP')
  209.  
  210. CONFIGURE_ENVIRONMENT['CFLAGS'] = CFLAGS
  211. CONFIGURE_ENVIRONMENT['CXXFLAGS'] = CXXFLAGS
  212. CONFIGURE_ENVIRONMENT['CPPFLAGS'] = CPPFLAGS
  213. CONFIGURE_ENVIRONMENT['CXXCPPFLAGS'] = CXXCPPFLAGS
  214. CONFIGURE_ENVIRONMENT['LDFLAGS'] = LDFLAGS
  215.  
  216. CONFIGURE_ENVIRONMENT.update(env.get('_%s-%s_CONFIGURE_ENVIRONMENT' % (product, target), {}))
  217. CONFIGURE_ENVIRONMENT.update(env.get('%s-%s_CONFIGURE_ENVIRONMENT' % (product, target), {}))
  218.  
  219. CONFIGURE_FLAGS = []
  220. CONFIGURE_FLAGS += ['--host=%s' % host_triple] if host_triple else []
  221. CONFIGURE_FLAGS += ['--cache-file=%s/%s-%s-%s.config.cache' % (CONFIGURE_DIR, product, target, CONFIGURATION)]
  222. CONFIGURE_FLAGS += ['--prefix=%s/%s-%s-%s' % (INSTALL_DIR, product, target, CONFIGURATION)]
  223. CONFIGURE_FLAGS += ['--enable-cxx'] if ENABLE_CXX else []
  224. # CONFIGURE_FLAGS += env['_cross-runtime_%s-%s_CONFIGURE_FLAGS' % (product, target)]
  225. CONFIGURE_FLAGS += env.get('_%s-%s_CONFIGURE_FLAGS' % (product, target), [])
  226. CONFIGURE_FLAGS += env.get('%s-%s_CONFIGURE_FLAGS' % (product, target), [])
  227.  
  228. env['_runtime_%s-%s_AC_VARS' % (product, target)] = AC_VARS
  229. env['_runtime_%s-%s_CONFIGURE_ENVIRONMENT' % (product, target)] = CONFIGURE_ENVIRONMENT
  230. env['_runtime_%s-%s_CONFIGURE_FLAGS' % (product, target)] = CONFIGURE_FLAGS
  231.  
  232.  
  233. def setup_android_target_template(env, target):
  234. extra_target_envs = {
  235. 'armeabi-v7a': {
  236. 'android-armeabi-v7a_CFLAGS': ['-D__POSIX_VISIBLE=201002', '-DSK_RELEASE', '-DNDEBUG', '-UDEBUG', '-fpic', '-march=armv7-a', '-mtune=cortex-a8', '-mfpu=vfp', '-mfloat-abi=softfp'],
  237. 'android-armeabi-v7a_CXXFLAGS': ['-D__POSIX_VISIBLE=201002', '-DSK_RELEASE', '-DNDEBUG', '-UDEBUG', '-fpic', '-march=armv7-a', '-mtune=cortex-a8', '-mfpu=vfp', '-mfloat-abi=softfp'],
  238. 'android-armeabi-v7a_LDFLAGS': ['-Wl,--fix-cortex-a8']
  239. },
  240. 'arm64-v8a': {
  241. 'android-arm64-v8a_CFLAGS': ['-D__POSIX_VISIBLE=201002', '-DSK_RELEASE', '-DNDEBUG', '-UDEBUG', '-fpic', '-DL_cuserid=9', '-DANDROID64'],
  242. 'android-arm64-v8a_CXXFLAGS': ['-D__POSIX_VISIBLE=201002', '-DSK_RELEASE', '-DNDEBUG', '-UDEBUG', '-fpic', '-DL_cuserid=9', '-DANDROID64']
  243. },
  244. 'x86': {},
  245. 'x86_64': {
  246. 'android-x86_64_CFLAGS': ['-DL_cuserid=9'],
  247. 'android-x86_64_CXXFLAGS': ['-DL_cuserid=9']
  248. }
  249. }
  250.  
  251. env.update(extra_target_envs[target])
  252.  
  253. android_new_ndk = True
  254.  
  255. with open(path_join(ANDROID_NDK_ROOT, 'source.properties')) as file:
  256. for line in file:
  257. line = line.strip()
  258. if line.startswith('Pkg.Revision ') or line.startswith('Pkg.Revision='):
  259. pkg_revision = line.split('=')[1].strip()
  260. mayor = int(pkg_revision.split('.')[0])
  261. android_new_ndk = mayor >= 18
  262. break
  263.  
  264. arch = AndroidTargetInfo.archs[target]
  265. abi_name = AndroidTargetInfo.abi_names[target]
  266. host_triple = AndroidTargetInfo.host_triples[target]
  267. api = env['ANDROID_API_VERSION']
  268.  
  269. toolchain_path = path_join(ANDROID_TOOLCHAINS_PREFIX, TOOLCHAIN_NAME_FMT % (target, api))
  270.  
  271. tools_path = path_join(toolchain_path, 'bin')
  272. name_fmt = abi_name + '-%s'
  273.  
  274. sdk_cmake_dir = path_join(ANDROID_SDK_ROOT, 'cmake', get_android_cmake_version())
  275. if not isdir(sdk_cmake_dir):
  276. print('Android CMake directory \'%s\' not found' % sdk_cmake_dir)
  277.  
  278. AR = path_join(tools_path, name_fmt % 'ar')
  279. AS = path_join(tools_path, name_fmt % 'as')
  280. CC = path_join(tools_path, name_fmt % 'clang')
  281. CXX = path_join(tools_path, name_fmt % 'clang++')
  282. DLLTOOL = ''
  283. LD = path_join(tools_path, name_fmt % 'ld')
  284. OBJDUMP = path_join(tools_path, name_fmt % 'objdump')
  285. RANLIB = path_join(tools_path, name_fmt % 'ranlib')
  286. CMAKE = path_join(sdk_cmake_dir, 'bin', 'cmake')
  287. STRIP = path_join(tools_path, name_fmt % 'strip')
  288.  
  289. CPP = path_join(tools_path, name_fmt % 'cpp')
  290. if not isfile(CPP):
  291. CPP = path_join(tools_path, (name_fmt % 'clang'))
  292. CPP += ' -E'
  293.  
  294. CXXCPP = path_join(tools_path, name_fmt % 'cpp')
  295. if not isfile(CXXCPP):
  296. CXXCPP = path_join(tools_path, (name_fmt % 'clang++'))
  297. CXXCPP += ' -E'
  298.  
  299. ccache_path = environ.get('CCACHE', '')
  300. if ccache_path:
  301. CC = '%s %s' % (ccache_path, CC)
  302. CXX = '%s %s' % (ccache_path, CXX)
  303. CPP = '%s %s' % (ccache_path, CPP)
  304. CXXCPP = '%s %s' % (ccache_path, CXXCPP)
  305.  
  306. AC_VARS = [
  307. 'mono_cv_uscore=yes',
  308. 'ac_cv_func_sched_getaffinity=no',
  309. 'ac_cv_func_sched_setaffinity=no',
  310. 'ac_cv_func_shm_open_working_with_mmap=no'
  311. ]
  312.  
  313. CFLAGS, CXXFLAGS, CPPFLAGS, CXXCPPFLAGS, LDFLAGS = [], [], [], [], []
  314.  
  315. CFLAGS += ['-fstack-protector']
  316. # CFLAGS += ['-DMONODROID=1']
  317. CFLAGS += ['-D__ANDROID_API__=' + api] if android_new_ndk else []
  318. CXXFLAGS += ['-fstack-protector']
  319. # CFLAGS += ['-DMONODROID=1']
  320. CXXFLAGS += ['-D__ANDROID_API__=' + api] if android_new_ndk else []
  321.  
  322. CPPFLAGS += ['-I%s/sysroot/usr/include' % toolchain_path]
  323. CXXCPPFLAGS += ['-I%s/sysroot/usr/include' % toolchain_path]
  324.  
  325. path_link = '%s/platforms/android-%s/arch-%s/usr/lib' % (ANDROID_NDK_ROOT, api, arch)
  326.  
  327. LDFLAGS += [
  328. '-z', 'now', '-z', 'relro', '-z', 'noexecstack',
  329. '-ldl', '-lm', '-llog', '-lc', '-lgcc',
  330. '-Wl,-rpath-link=%s,-dynamic-linker=/system/bin/linker' % path_link,
  331. '-L' + path_link
  332. ]
  333.  
  334. CONFIGURE_FLAGS = [
  335. '--disable-boehm',
  336. '--disable-executables',
  337. '--disable-iconv',
  338. '--disable-mcs-build',
  339. '--disable-nls',
  340. '--enable-dynamic-btls',
  341. '--enable-maintainer-mode',
  342. '--enable-minimal=ssa,portability,attach,verifier,full_messages,sgen_remset'
  343. ',sgen_marksweep_par,sgen_marksweep_fixed,sgen_marksweep_fixed_par'
  344. ',sgen_copying,logging,security,shared_handles,interpreter',
  345. # '--enable-monodroid',
  346. '--with-btls-android-ndk=%s' % ANDROID_NDK_ROOT,
  347. '--with-btls-android-api=%s' % api,
  348. ]
  349.  
  350. CONFIGURE_FLAGS += ['--with-btls-android-ndk-asm-workaround'] if android_new_ndk else []
  351.  
  352. CONFIGURE_FLAGS += [
  353. '--with-btls-android-cmake-toolchain=%s/build/cmake/android.toolchain.cmake' % ANDROID_NDK_ROOT,
  354. '--with-sigaltstack=yes',
  355. '--with-tls=pthread',
  356. '--without-ikvm-native',
  357. '--disable-cooperative-suspend',
  358. '--disable-hybrid-suspend',
  359. '--disable-crash-reporting'
  360. ]
  361.  
  362. env['_android-%s_AR' % target] = AR
  363. env['_android-%s_AS' % target] = AS
  364. env['_android-%s_CC' % target] = CC
  365. env['_android-%s_CXX' % target] = CXX
  366. env['_android-%s_CPP' % target] = CPP
  367. env['_android-%s_CXXCPP' % target] = CXXCPP
  368. env['_android-%s_DLLTOOL' % target] = DLLTOOL
  369. env['_android-%s_LD' % target] = LD
  370. env['_android-%s_OBJDUMP' % target] = OBJDUMP
  371. env['_android-%s_RANLIB' % target] = RANLIB
  372. env['_android-%s_CMAKE' % target] = CMAKE
  373. env['_android-%s_STRIP' % target] = STRIP
  374.  
  375. env['_android-%s_AC_VARS' % target] = AC_VARS
  376. env['_android-%s_CFLAGS' % target] = CFLAGS
  377. env['_android-%s_CXXFLAGS' % target] = CXXFLAGS
  378. env['_android-%s_CPPFLAGS' % target] = CPPFLAGS
  379. env['_android-%s_CXXCPPFLAGS' % target] = CXXCPPFLAGS
  380. env['_android-%s_LDFLAGS' % target] = LDFLAGS
  381. env['_android-%s_CONFIGURE_FLAGS' % target] = CONFIGURE_FLAGS
  382.  
  383. setup_runtime_template(env, 'android', target, host_triple)
  384.  
  385.  
  386. def make_standalone_toolchain(target, api):
  387. install_dir = path_join(ANDROID_TOOLCHAINS_PREFIX, TOOLCHAIN_NAME_FMT % (target, api))
  388. if isdir(path_join(install_dir, 'bin')):
  389. return # Looks like it's already there, so no need to re-create it
  390. command = path_join(ANDROID_NDK_ROOT, 'build', 'tools', 'make_standalone_toolchain.py')
  391. args = ['--verbose', '--force', '--api=' + api, '--arch=' + AndroidTargetInfo.archs[target],
  392. '--install-dir=' + install_dir]
  393. run_command(command, args=args, name='make_standalone_toolchain')
  394.  
  395.  
  396. def strip_libs(product, target, api):
  397. toolchain_path = path_join(ANDROID_TOOLCHAINS_PREFIX, TOOLCHAIN_NAME_FMT % (target, api))
  398.  
  399. tools_path = path_join(toolchain_path, 'bin')
  400. name_fmt = AndroidTargetInfo.abi_names[target] + '-%s'
  401.  
  402. STRIP = path_join(tools_path, name_fmt % 'strip')
  403.  
  404. install_dir = '%s/%s-%s-%s' % (INSTALL_DIR, product, target, CONFIGURATION)
  405. out_libs_dir = path_join(install_dir, 'lib')
  406.  
  407. lib_files = globs(('*.a', '*.so'), dirpath=out_libs_dir)
  408. if len(lib_files):
  409. run_command(STRIP, args=['--strip-unneeded'] + lib_files, name='strip')
  410.  
  411.  
  412. def configure(product, target):
  413. env = { 'ANDROID_API_VERSION': get_api_version_or_min(target) }
  414.  
  415. make_standalone_toolchain(target, env['ANDROID_API_VERSION'])
  416.  
  417. setup_android_target_template(env, target)
  418.  
  419. chdir(MONO_SOURCE_ROOT)
  420. autogen_env = environ.copy()
  421. autogen_env['NOCONFIGURE'] = '1'
  422. run_command(path_join(MONO_SOURCE_ROOT, 'autogen.sh'), custom_env=autogen_env, name='autogen')
  423.  
  424. build_dir = CONFIGURE_DIR + '/%s-%s-%s' % (product, target, CONFIGURATION)
  425. mkdir_p(build_dir)
  426. chdir(build_dir)
  427.  
  428. def str_dict_val(val):
  429. if isinstance(val, list):
  430. return ' '.join(val) # No need for quotes
  431. return val
  432.  
  433. ac_vars = env['_runtime_%s-%s_AC_VARS' % (product, target)]
  434. configure_env = env['_runtime_%s-%s_CONFIGURE_ENVIRONMENT' % (product, target)]
  435. configure_env = [('%s=%s' % (key, str_dict_val(value))) for (key, value) in configure_env.items()]
  436. configure_flags = env['_runtime_%s-%s_CONFIGURE_FLAGS' % (product, target)]
  437.  
  438. command = path_join(MONO_SOURCE_ROOT, 'configure')
  439. configure_args = ac_vars + configure_env + configure_flags
  440.  
  441. run_command(command, args=configure_args, name='configure')
  442.  
  443.  
  444. def make(product, target):
  445. env = { 'ANDROID_API_VERSION': get_api_version_or_min(target) }
  446.  
  447. build_dir = CONFIGURE_DIR + '/%s-%s-%s' % (product, target, CONFIGURATION)
  448. chdir(build_dir)
  449.  
  450. make_args = ['V=1'] if VERBOSE_MAKE else []
  451.  
  452. run_command('make', args=make_args, name='make')
  453. run_command('make', args=['install'], name='make install')
  454.  
  455. if STRIP_LIBS:
  456. strip_libs(product, target, env['ANDROID_API_VERSION'])
  457.  
  458.  
  459. def clean(product, target):
  460. rm_rf(
  461. CONFIGURE_DIR + '/toolchains/%s-%s' % (product, target),
  462. CONFIGURE_DIR + '/%s-%s-%s' % (product, target, CONFIGURATION),
  463. CONFIGURE_DIR + '/%s-%s-%s.config.cache' % (product, target, CONFIGURATION),
  464. INSTALL_DIR + '/%s-%s-%s' % (product, target, CONFIGURATION)
  465. )
  466.  
  467.  
  468. def set_arguments(args):
  469. global CONFIGURATION, RELEASE, ANDROID_TOOLCHAINS_PREFIX, ANDROID_SDK_ROOT, \
  470. ANDROID_NDK_ROOT, _ANDROID_API_VERSION, _ANDROID_CMAKE_VERSION, ENABLE_CXX, \
  471. VERBOSE_MAKE, STRIP_LIBS, CONFIGURE_DIR, INSTALL_DIR, MONO_SOURCE_ROOT, CONFIGURATION
  472.  
  473. # Need to make paths absolute as we change cwd later
  474.  
  475. CONFIGURATION = args.configuration
  476. RELEASE = (CONFIGURATION == 'release')
  477. ANDROID_TOOLCHAINS_PREFIX = abspath(args.toolchains_prefix)
  478. ANDROID_SDK_ROOT = abspath(args.android_sdk)
  479. ANDROID_NDK_ROOT = abspath(args.android_ndk)
  480. ENABLE_CXX = args.enable_cxx
  481. VERBOSE_MAKE = args.verbose_make
  482. STRIP_LIBS = args.strip_libs
  483. CONFIGURE_DIR = abspath(args.configure_dir)
  484. INSTALL_DIR = abspath(args.install_dir)
  485. MONO_SOURCE_ROOT = abspath(args.mono_sources)
  486.  
  487. _ANDROID_API_VERSION = args.android_api_version
  488. _ANDROID_CMAKE_VERSION = args.android_cmake_version
  489.  
  490.  
  491. def main(raw_args):
  492. import argparse
  493.  
  494. from collections import OrderedDict
  495. from textwrap import dedent
  496.  
  497. target_indiv_values = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
  498. target_values = target_indiv_values + ['all']
  499.  
  500. actions = OrderedDict()
  501. actions['configure'] = configure
  502. actions['make'] = make
  503. actions['clean'] = clean
  504.  
  505. parser = argparse.ArgumentParser(
  506. description='Builds the Mono runtime for Android',
  507. formatter_class=argparse.RawDescriptionHelpFormatter,
  508. epilog=dedent('''\
  509. environment variables:
  510. ANDROID_SDK_ROOT: Overrides default value for --android-sdk
  511. ANDROID_NDK_ROOT: Overrides default value for --android-ndk
  512. MONO_SOURCE_ROOT: Overrides default value for --mono-sources
  513. ANDROID_HOME: Same as ANDROID_SDK_ROOT
  514. ''')
  515. )
  516.  
  517. home = environ.get('HOME')
  518. android_sdk_default = environ.get('ANDROID_HOME', environ.get('ANDROID_SDK_ROOT', path_join(home, 'Android/Sdk')))
  519. android_ndk_default = environ.get('ANDROID_NDK_ROOT', path_join(android_sdk_default, 'ndk-bundle'))
  520. mono_sources_default = environ.get('MONO_SOURCE_ROOT', '')
  521.  
  522. default_help = dedent('default: %(default)s')
  523.  
  524. parser.add_argument('action', choices=['configure', 'make', 'clean'])
  525. parser.add_argument('--target', choices=target_values, action='append', required=True)
  526. parser.add_argument('--configuration', choices=['release', 'debug'], default='release', help=default_help)
  527. parser.add_argument('--toolchains-prefix', default=path_join(home, 'android-toolchains'), help=default_help)
  528. parser.add_argument('--android-sdk', default=android_sdk_default, help=default_help)
  529. parser.add_argument('--android-ndk', default=android_ndk_default, help=default_help)
  530. parser.add_argument('--android-api-version', default='18', help=default_help)
  531. parser.add_argument('--android-cmake-version', default='autodetect', help=default_help)
  532. parser.add_argument('--enable-cxx', action='store_true', default=False, help=default_help)
  533. parser.add_argument('--verbose-make', action='store_true', default=False, help=default_help)
  534. parser.add_argument('--strip-libs', action='store_true', default=True, help=default_help)
  535. parser.add_argument('--configure-dir', default=path_join(home, 'mono-configs'), help=default_help)
  536. parser.add_argument('--install-dir', default=path_join(home, 'mono-installs'), help=default_help)
  537.  
  538. if mono_sources_default:
  539. parser.add_argument('--mono-sources', default=mono_sources_default, help=default_help)
  540. else:
  541. parser.add_argument('--mono-sources')
  542.  
  543. args = parser.parse_args(raw_args)
  544.  
  545. action = args.action
  546. targets = args.target
  547.  
  548. set_arguments(args)
  549.  
  550. if not isdir(MONO_SOURCE_ROOT):
  551. print('Mono sources directory not found: ' + MONO_SOURCE_ROOT)
  552. exit(1)
  553.  
  554. android_targets = []
  555.  
  556. if 'all' in targets:
  557. android_targets = target_indiv_values[:]
  558. else:
  559. for target in targets:
  560. if not target in android_targets:
  561. android_targets += [target]
  562.  
  563. action_fn = actions[action]
  564.  
  565. try:
  566. for target in android_targets:
  567. action_fn('android', target)
  568. except MonoBuildError as e:
  569. exit(e.message)
  570.  
  571.  
  572. if __name__ == '__main__':
  573. from sys import argv
  574. main(argv[1:])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement