You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

meson.build 10 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. # Conventions:
  2. # _ implies that the variables are not meant to be used outside here
  3. # Optionals are applied from the top-level meson_options.txt
  4. # They are declared at the top
  5. # Typically derived from (in order) the CMakeLists.txt and Makefiles
  6. #
  7. # Installation:
  8. # meson setup build --buildtype release
  9. # meson compile -C build
  10. # meson install --prefix=$HOME/.local/lapack
  11. #
  12. # NOTE: This is still a work in progress, the Makefiles are canonical
  13. project('OpenBLAS', ['c', 'fortran'],
  14. default_options: ['c_std=c99'],
  15. version: '0.3.26.dev')
  16. openblas_major_version = 0 # soversion
  17. openblas_minor_version = 3
  18. openblas_patch_version = '26.dev'
  19. openblas_version = f'@openblas_major_version@.@openblas_minor_version@.@openblas_patch_version@'
  20. # Skip the check for valid CC
  21. cc = meson.get_compiler('c')
  22. fc = meson.get_compiler('fortran')
  23. fc_id = fc.get_id()
  24. # Common args
  25. _args = []
  26. _cargs = []
  27. _fargs = []
  28. # System configuration
  29. build_single = get_option('build_single')
  30. build_double = get_option('build_double')
  31. build_complex = get_option('build_complex')
  32. build_complex16 = get_option('build_complex16')
  33. # TODO: Be conditional
  34. _cargs = [
  35. '-DBUILD_SINGLE=1',
  36. '-DBUILD_DOUBLE=1',
  37. '-DBUILD_COMPLEX=1',
  38. '-DBUILD_COMPLEX16=1',
  39. ]
  40. # Options from CMakelists
  41. build_without_lapack = get_option('build_without_lapack')
  42. build_lapack_deprecated = get_option('build_lapack_deprecated')
  43. build_testing = get_option('build_testing')
  44. use_c_lapack = get_option('use_c_lapack')
  45. build_without_cblas = get_option('build_without_cblas')
  46. dynamic_arch = get_option('dynamic_arch')
  47. dynamic_older = get_option('dynamic_older')
  48. build_relapack = get_option('build_relapack')
  49. use_locking = get_option('use_locking')
  50. use_perl = get_option('use_perl')
  51. no_warmup = get_option('no_warmup')
  52. no_affinity = get_option('no_affinity')
  53. build_cpp_thread_safety_test = get_option('build_cpp_thread_safety_test')
  54. build_cpp_thread_safety_gemv = get_option('build_cpp_thread_safety_gemv')
  55. build_static_libs = get_option('build_static_libs')
  56. max_stack_alloc = get_option('max_stack_alloc')
  57. if host_machine.system() == 'linux'
  58. no_affinity = true
  59. else
  60. no_affinity = false
  61. endif
  62. # Makefile.prebuild stuff
  63. # TODO: Handle cpuidemu, and the target flags
  64. # getarch = executable('getarch',
  65. # ['getarch.c', 'cpuid.S'])
  66. # getarch_two = executable('getarch_2nd',
  67. # ['getarch_2nd.c'])
  68. # config_h = custom_target('gen_config_h',
  69. # # input: ['getarch.c'],
  70. # output: ['config.h'],
  71. # command: [getarch, '3']
  72. # )
  73. _check_prefix = []
  74. conf_data = configuration_data()
  75. is_win = host_machine.system() == 'windows' or host_machine.system() == 'cygwin'
  76. conf_data.set('OS_WINDOWS', is_win)
  77. hostcpu = host_machine.cpu_family()
  78. conf_data.set('ARCH', hostcpu.to_upper())
  79. defarch_array = [
  80. # {'system': ['windows', 'cygwin'], 'def': ['OS_WINDOWS']},
  81. {'cpu': ['aarch64'], 'def': ['ARCH_ARGM64']},
  82. {'cpu': ['alpha'], 'def': ['ARCH_ALPHA']},
  83. {'cpu': ['arm'], 'def': ['ARCH_ARM', 'USE_TRMM']},
  84. {'cpu': ['x86_64'], 'def': ['INTEL_AMD', 'USE_GEMM3M', 'USE_DIRECT_SGEMM']},
  85. {'cpu': ['s390x'], 'def': ['ARCH_ZARCH', 'ZARCH']},
  86. {'cpu': ['ia64'], 'def': ['ARCH_IA64', 'USE_GEMM3M']},
  87. {'cpu': ['sparc'], 'def': ['ARCH_SPARC']},
  88. {'cpu': ['mips'], 'def': ['ARCH_MIPS']},
  89. {'cpu': ['mips64'], 'def': ['ARCH_MIPS64', 'USE_TRMM']},
  90. {'cpu': ['loongarch64'], 'def': ['ARCH_LOONGARCH64']},
  91. {'cpu': ['riscv64'], 'def': ['ARCH_RISCV64', 'USE_TRMM']},
  92. {'cpu': ['ppc64', 'ppc'], 'def': ['ARCH_POWER', 'POWER']},
  93. {'cpu': ['generic'], 'def': ['USE_TRMM']},
  94. ]
  95. # TODO(rg): Handle the kenel architectures later
  96. foreach arch : defarch_array
  97. is_cpu = hostcpu in arch['cpu']
  98. foreach def : arch['def']
  99. conf_data.set(def, is_cpu)
  100. endforeach
  101. endforeach
  102. configure_file(output : 'getarch_conf.h',
  103. configuration : conf_data)
  104. # run_target('generate_config_h',
  105. # command: [meson.current_build_dir() + '/getarch', '1'],
  106. # depends: getarch)
  107. # gch = run_command(meson.current_build_dir() + '/getarch', '1')
  108. # outp = gch.stdout().strip()
  109. # conf_data = configuration_data()
  110. # configure_file(input : meson.current_build_dir() + '/config.h',
  111. # output : 'config.h',
  112. # configuration : conf_data)
  113. # Makefile.system
  114. cpu_fam = target_machine.cpu_family()
  115. if cpu_fam in ['x86_64', 'ppc64', 'ppc']
  116. add_project_arguments([
  117. '-DSMALL_MATRIX_OPT',
  118. f'-DMAX_STACK_ALLOC=@max_stack_alloc@',
  119. ], language:'c')
  120. endif
  121. if cpu_fam == 'x86_64'
  122. _cargs += ['-m64']
  123. endif
  124. if fc_id == 'gcc'
  125. add_project_arguments('-DF_INTERFACE_GFORT', language: 'c')
  126. else
  127. upper_fcid = fc_id.to_upper()
  128. add_project_arguments(f'-DF_INTERFACE_@upper_fcid@', language: 'c')
  129. endif
  130. simd_extensions = [
  131. {'flag': '-mmmx', 'define': 'HAVE_MMX'},
  132. {'flag': '-msse', 'define': 'HAVE_SSE'},
  133. {'flag': '-msse2', 'define': 'HAVE_SSE2'},
  134. {'flag': '-msse3', 'define': 'HAVE_SSE3'},
  135. {'flag': '-mssse3', 'define': 'HAVE_SSSE3'},
  136. {'flag': '-msse4.1', 'define': 'HAVE_SSE4_1'},
  137. {'flag': '-msse4.2', 'define': 'HAVE_SSE4_2'},
  138. {'flag': '-mfma', 'define': 'HAVE_FMA3'},
  139. {'flag': '-mavx', 'define': 'HAVE_AVX'},
  140. {'flag': '-mavx2', 'define': 'HAVE_AVX2'},
  141. ]
  142. simd_cargs = []
  143. simd_conf_data = configuration_data()
  144. foreach ext : simd_extensions
  145. if cc.has_argument(ext['flag'])
  146. simd_cargs += ext['flag']
  147. simd_conf_data.set(ext['define'], true)
  148. else
  149. simd_conf_data.set(ext['define'], false)
  150. endif
  151. endforeach
  152. # Generate configuration header
  153. configure_file(output : 'simd_conf.h',
  154. configuration : simd_conf_data)
  155. # Can't be added as a project argument since it won't be generated until later
  156. bldroot = meson.build_root()
  157. _cargs += ['-include', f'@bldroot@/simd_conf.h']
  158. add_project_arguments(simd_cargs, language: 'c')
  159. # Common symbol related options
  160. symnames = ['ASMNAME', 'ASMFNAME', 'NAME', 'CNAME', 'CHAR_NAME', 'CHAR_CNAME']
  161. # Other common options, move later
  162. # Undefine to help prevent clashes
  163. foreach symb : symnames
  164. _cargs += f'-U@symb@'
  165. endforeach
  166. # Based on options
  167. if not build_without_cblas
  168. _cargs += '-DCBLAS'
  169. endif
  170. if no_affinity
  171. _cargs += '-DNO_AFFINITY'
  172. endif
  173. if no_warmup
  174. _cargs += '-DNO_WARMUP'
  175. endif
  176. # Parallel builds
  177. # TODO: This can be cleaned up significantly
  178. # Also use multiprocessing.cpu_count()
  179. # TODO: Handle SMP_SERVER
  180. num_parallel = get_option('num_parallel')
  181. if num_parallel > 1
  182. _cargs += f'-DMAX_PARALLEL_NUMBER=@num_parallel@'
  183. endif
  184. num_cores = get_option('num_cores')
  185. if num_cores > 0
  186. num_threads = num_cores
  187. else
  188. num_threads = 0
  189. endif
  190. use_thread = false
  191. if num_threads > 2
  192. use_thread = true
  193. endif
  194. if use_thread
  195. message('Multi-threading enabled with ' + num_threads.to_string() + ' threads.')
  196. _cargs += f'-DMAX_CPU_NUMBER=@num_threads@'
  197. _cargs += f'-DSMP_SERVER'
  198. else
  199. if get_option('use_locking')
  200. _cargs += '-DUSE_LOCKING'
  201. endif
  202. endif
  203. # Common maps
  204. # Naming conventions: https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2024-1/naming-conventions-for-blas-routines.html
  205. # Also see:
  206. # L1: https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2024-1/blas-level-1-routines-and-functions.html
  207. precision_mappings = {
  208. 's': {'undef': ['COMPLEX', 'DOUBLE']},
  209. 'd': {'undef': ['COMPLEX'], 'def': ['DOUBLE']},
  210. 'q': {'undef': ['COMPLEX'], 'def': ['XDOUBLE']},
  211. 'c': {'undef': ['DOUBLE'], 'def': ['COMPLEX']},
  212. 'z': {'def': ['COMPLEX', 'DOUBLE']},
  213. 'x': {'def': ['COMPLEX', 'XDOUBLE']},
  214. 'cs': {'undef': ['DOUBLE'], 'def': ['COMPLEX']},
  215. 'sc': {'undef': ['DOUBLE'], 'def': ['COMPLEX']},
  216. 'dz': {'def': ['COMPLEX', 'DOUBLE']},
  217. 'zd': {'def': ['COMPLEX', 'DOUBLE']},
  218. 'qx': {'def': ['COMPLEX', 'XDOUBLE']},
  219. 'xq': {'def': ['COMPLEX', 'XDOUBLE']},
  220. '': {}, # special case, for cblas_?dot*_sub
  221. # NOTE: Anything with XDOUBLE aka longdouble has no cblas_
  222. # xq / qx == x
  223. # sc / cs == c
  224. # zd / dz is the same as z
  225. # 'zd': {'undef': [], 'def': ['COMPLEX', 'DOUBLE']},
  226. }
  227. ext_mappings = {
  228. '': {}, # special case
  229. '_k': {},
  230. '_U': {'undef': ['LOWER']},
  231. '_L': {'def': ['LOWER']},
  232. '_V': {'def': ['HEMV', 'HEMVREV'], 'undef': ['LOWER']},
  233. '_M': {'def': ['HEMV', 'HEMVREV', 'LOWER']},
  234. '_n': {'undef': ['TRANS', 'CONJ', 'XCONJ']},
  235. '_t': {'def': ['TRANS'], 'undef': ['CONJ', 'XCONJ']},
  236. '_r': {'def': ['CONJ'], 'undef': ['TRANS', 'XCONJ']},
  237. '_c': {'def': ['TRANS', 'CONJ'], 'undef': ['XCONJ']},
  238. '_o': {'def': ['XCONJ'], 'undef': ['TRANS', 'CONJ']},
  239. '_u': {'def': ['TRANS', 'XCONJ'], 'undef': ['CONJ']},
  240. '_s': {'def': ['CONJ', 'XCONJ'], 'undef': ['TRANS']},
  241. '_d': {'def': ['TRANS', 'CONJ', 'XCONJ']},
  242. }
  243. symb_defs = {
  244. '?amax': {'def': ['USE_ABS'], 'undef': ['USE_MIN']},
  245. '?amin': {'def': ['USE_ABS', 'USE_MIN']},
  246. 'i?max': {'undef': ['USE_ABS', 'USE_MIN']},
  247. 'i?amax': {'def': ['USE_ABS'], 'undef': ['USE_MIN']},
  248. 'i?amin': {'def': ['USE_ABS', 'USE_MIN']},
  249. 'i?min': {'def': ['USE_MIN'], 'undef': ['USE_ABS']},
  250. '?max': {'undef': ['USE_ABS', 'USE_MIN']},
  251. '?min': {'def': ['USE_MIN'], 'undef': ['USE_ABS']},
  252. '?axpyc': {'def': ['CONJ']},
  253. '?dotu': {'undef': ['CONJ']},
  254. '?dotc': {'def': ['CONJ']},
  255. '?geru': {'undef': ['CONJ']},
  256. '?gerc': {'def': ['CONJ']},
  257. '?hemm': {'def': ['HEMM']},
  258. '?herk': {'def': ['HEMM']},
  259. '?her2k': {'def': ['HEMM']},
  260. '?gemm3m': {'def': ['GEMM3M']},
  261. '?symm3m': {'def': ['GEMM3M']},
  262. '?hemm3m': {'def': ['HEMM', 'GEMM3M']},
  263. 'cblas_?dotu_sub': {'def': ['CBLAS', 'FORCE_USE_STACK'], 'undef': ['CONJ']},
  264. 'cblas_?dotc_sub': {'def': ['CBLAS', 'FORCE_USE_STACK', 'CONJ']},
  265. }
  266. # Ignoring other hostarch checks and conflicts for arch in BSD for now
  267. _inc = [include_directories('.')]
  268. # subdir('lapack-netlib')
  269. subdir('interface')
  270. subdir('kernel')
  271. _openblas = static_library('openblas',
  272. link_whole: [ _interface, _kern])