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.

utils.cmake 22 kB

5 years ago
8 years ago
5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531
  1. # Functions to help with the OpenBLAS build
  2. # Reads string from getarch into CMake vars. Format of getarch vars is VARNAME=VALUE
  3. function(ParseGetArchVars GETARCH_IN)
  4. string(REGEX MATCHALL "[0-9_a-zA-Z]+=[0-9_a-zA-Z]+" GETARCH_RESULT_LIST "${GETARCH_IN}")
  5. foreach (GETARCH_LINE ${GETARCH_RESULT_LIST})
  6. # split the line into var and value, then assign the value to a CMake var
  7. string(REGEX MATCHALL "[0-9_a-zA-Z]+" SPLIT_VAR "${GETARCH_LINE}")
  8. list(GET SPLIT_VAR 0 VAR_NAME)
  9. list(GET SPLIT_VAR 1 VAR_VALUE)
  10. set(${VAR_NAME} ${VAR_VALUE} PARENT_SCOPE)
  11. endforeach ()
  12. endfunction ()
  13. # Reads a Makefile into CMake vars.
  14. macro(ParseMakefileVars MAKEFILE_IN)
  15. message(STATUS "Reading vars from ${MAKEFILE_IN}...")
  16. set (C_COMPILER ${CMAKE_C_COMPILER_ID})
  17. set (IfElse 0)
  18. set (ElseSeen 0)
  19. set (SkipIfs 0)
  20. set (SkipElse 0)
  21. file(STRINGS ${MAKEFILE_IN} makefile_contents)
  22. foreach (makefile_line ${makefile_contents})
  23. #message(STATUS "parsing ${makefile_line}")
  24. # Skip the entire scope of the else statement given that the if statement that precedes it has the valid condition.
  25. # The variable SkipIfs is used to identify which endif statement closes the scope of the else statement.
  26. if (${SkipElse} EQUAL 1)
  27. #message(STATUS "skipping ${makefile_line}")
  28. string(REGEX MATCH "(ifeq|ifneq|ifdef|ifndef) .*$" line_match "${makefile_line}")
  29. if (NOT "${line_match}" STREQUAL "")
  30. MATH(EXPR SkipIfs "${SkipIfs}+1")
  31. endif ()
  32. string(REGEX MATCH "endif[ \t]*" line_match "${makefile_line}")
  33. if (NOT "${line_match}" STREQUAL "")
  34. if (${SkipIfs} EQUAL 0)
  35. set (SkipElse 0)
  36. else ()
  37. MATH(EXPR SkipIfs "${SkipIfs}-1")
  38. endif ()
  39. endif ()
  40. continue ()
  41. endif ()
  42. # The variable IfElse is greater than 0 if and only if the previously parsed line is an if statement.
  43. if (${IfElse} GREATER 0)
  44. # If the current scope is the one that has to be skipped, the if/endif/else statements
  45. # along with it till the endif that closes the current scope have to be ignored as well.
  46. string(REGEX MATCH "(ifeq|ifneq|ifdef|ifndef) .*$" line_match "${makefile_line}")
  47. if (NOT "${line_match}" STREQUAL "")
  48. if ((${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR (${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1))
  49. #message(STATUS "skipping ${makefile_line}")
  50. MATH(EXPR SkipIfs "${SkipIfs}+1")
  51. continue ()
  52. endif ()
  53. endif ()
  54. string(REGEX MATCH "endif[ \t]*" line_match "${makefile_line}")
  55. if (NOT "${line_match}" STREQUAL "")
  56. if (${SkipIfs} EQUAL 0)
  57. #message(STATUS "ENDIF ${makefile_line}")
  58. set (IfElse 0)
  59. set (ElseSeen 0)
  60. else ()
  61. #message(STATUS "skipping ${makefile_line}")
  62. MATH(EXPR SkipIfs "${SkipIfs}-1")
  63. endif ()
  64. continue ()
  65. endif ()
  66. string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}")
  67. if (NOT "${line_match}" STREQUAL "")
  68. if (${SkipIfs} EQUAL 0)
  69. #message(STATUS "ELSE ${makefile_line}")
  70. set (ElseSeen 1)
  71. else ()
  72. #message(STATUS "skipping ${makefile_line}")
  73. endif ()
  74. continue ()
  75. endif()
  76. # Skip the lines that are not part of the path that has to be taken.
  77. if ((${IfElse} EQUAL 2 AND ${ElseSeen} EQUAL 0) OR (${IfElse} EQUAL 1 AND ${ElseSeen} EQUAL 1) OR (${SkipIfs} GREATER 0))
  78. #message(STATUS "skipping ${makefile_line}")
  79. continue ()
  80. endif ()
  81. endif ()
  82. # Skip commented lines (the ones that start with '#')
  83. string(REGEX MATCH "[ \t]*\\#.*$" line_match "${makefile_line}")
  84. if (NOT "${line_match}" STREQUAL "")
  85. #message(STATUS "skipping ${makefile_line}")
  86. continue ()
  87. endif ()
  88. string(REGEX MATCH "([0-9_a-zA-Z]+)[ \t]*=[ \t]*(.+)$" line_match "${makefile_line}")
  89. if (NOT "${line_match}" STREQUAL "")
  90. #message(STATUS "match on ${line_match}")
  91. set(var_name ${CMAKE_MATCH_1})
  92. #set(var_value ${CMAKE_MATCH_2})
  93. string(STRIP ${CMAKE_MATCH_2} var_value)
  94. # check for Makefile variables in the string, e.g. $(TSUFFIX)
  95. string(REGEX MATCHALL "\\$\\(([0-9_a-zA-Z]+)\\)" make_var_matches ${var_value})
  96. foreach (make_var ${make_var_matches})
  97. # strip out Makefile $() markup
  98. string(REGEX REPLACE "\\$\\(([0-9_a-zA-Z]+)\\)" "\\1" make_var ${make_var})
  99. # now replace the instance of the Makefile variable with the value of the CMake variable (note the double quote)
  100. string(REPLACE "$(${make_var})" "${${make_var}}" var_value ${var_value})
  101. endforeach ()
  102. set(${var_name} ${var_value})
  103. continue ()
  104. endif ()
  105. # Include a new file to be parsed
  106. string(REGEX MATCH "include \\$\\(KERNELDIR\\)/(.+)$" line_match "${makefile_line}")
  107. if (NOT "${line_match}" STREQUAL "")
  108. #message(STATUS "match on include ${line_match}")
  109. ParseMakefileVars(${KERNELDIR}/${CMAKE_MATCH_1})
  110. continue ()
  111. endif ()
  112. # The if statement that precedes this else has the path taken
  113. # Thus, this else statement has to be skipped.
  114. string(REGEX MATCH "else[ \t]*" line_match "${makefile_line}")
  115. if (NOT "${line_match}" STREQUAL "")
  116. #message(STATUS "skipping ${makefile_line}")
  117. set (SkipElse 1)
  118. continue()
  119. endif()
  120. # Example 1: ifdef HAVE_MSA
  121. # Example 2: ifndef ZNRM2KERNEL
  122. string(REGEX MATCH "(ifdef|ifndef) ([0-9_A-Z]+)" line_match "${makefile_line}")
  123. if (NOT "${line_match}" STREQUAL "")
  124. #message(STATUS "${CMAKE_MATCH_1} first: ${CMAKE_MATCH_2}")
  125. set (ElseSeen 0)
  126. if (${CMAKE_MATCH_2})
  127. if (${CMAKE_MATCH_1} STREQUAL "ifdef")
  128. #message (STATUS "condition is true")
  129. set (IfElse 1)
  130. else ()
  131. set (IfElse 2)
  132. endif ()
  133. else ()
  134. if (${CMAKE_MATCH_1} STREQUAL "ifdef")
  135. set (IfElse 2)
  136. else ()
  137. #message (STATUS "condition is true")
  138. set (IfElse 1)
  139. endif ()
  140. endif ()
  141. continue ()
  142. endif ()
  143. # Example 1: ifeq ($(SGEMM_UNROLL_M), 16)
  144. # Example 2: ifeq ($(SGEMM_UNROLL_M)x$(SGEMM_UNROLL_N), 8x8)
  145. # Example 3: ifeq ($(__BYTE_ORDER__)$(ELF_VERSION),__ORDER_BIG_ENDIAN__2)
  146. # Ignore the second group since (?:...) does not work on cmake
  147. string(REGEX MATCH "ifeq \\(\\$\\(([0-9_A-Z]+)\\)(([0-9_A-Za-z]*)\\$\\(([0-9_A-Z]+)\\))?,[ \t]*([0-9_A-Za-z]+)\\)" line_match "${makefile_line}")
  148. if (NOT "${line_match}" STREQUAL "")
  149. #message(STATUS "IFEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_3} third: ${CMAKE_MATCH_4} fourth: ${CMAKE_MATCH_5}")
  150. if (DEFINED ${CMAKE_MATCH_1})
  151. if (DEFINED ${CMAKE_MATCH_4})
  152. set (STR ${${CMAKE_MATCH_1}}${CMAKE_MATCH_3}${${CMAKE_MATCH_4}})
  153. else ()
  154. set (STR ${${CMAKE_MATCH_1}})
  155. endif ()
  156. if (${STR} STREQUAL ${CMAKE_MATCH_5})
  157. #message (STATUS "condition is true")
  158. set (IfElse 1)
  159. continue ()
  160. endif ()
  161. endif ()
  162. set (IfElse 2)
  163. continue ()
  164. endif ()
  165. # Example 1 (Group 3): ifneq ($(SGEMM_UNROLL_M), $(SGEMM_UNROLL_N))
  166. # Example 2 (Group 4): ifneq ($(C_COMPILER), PGI)
  167. string(REGEX MATCH "ifneq \\(\\$\\(([0-9_A-Z]+)\\),[ \t]*(\\$\\(([0-9_A-Z]+)\\)|([0-9_A-Z]+))\\)" line_match "${makefile_line}")
  168. if (NOT "${line_match}" STREQUAL "")
  169. #message(STATUS "IFNEQ: ${line_match} first: ${CMAKE_MATCH_1} second: ${CMAKE_MATCH_3} third: ${CMAKE_MATCH_4}")
  170. set (ElseSeen 0)
  171. set (HasValidGroup 0)
  172. if (DEFINED ${CMAKE_MATCH_3})
  173. set (HasValidGroup 1)
  174. set (STR ${${CMAKE_MATCH_3}})
  175. elseif (NOT ${CMAKE_MATCH_4} STREQUAL "")
  176. set (HasValidGroup 1)
  177. set (STR ${CMAKE_MATCH_4})
  178. endif ()
  179. if (DEFINED ${CMAKE_MATCH_1} AND ${HasValidGroup} EQUAL 1)
  180. if (NOT (${${CMAKE_MATCH_1}} STREQUAL ${STR}))
  181. #message (STATUS "condition is true")
  182. set (IfElse 1)
  183. continue ()
  184. endif ()
  185. endif ()
  186. set (IfElse 2)
  187. continue ()
  188. endif ()
  189. #message(STATUS "unmatched line ${line_match}")
  190. endforeach ()
  191. endmacro ()
  192. # Returns all combinations of the input list, as a list with colon-separated combinations
  193. # E.g. input of A B C returns A B C A:B A:C B:C
  194. # N.B. The input is meant to be a list, and to past a list to a function in CMake you must quote it (e.g. AllCombinations("${LIST_VAR}")).
  195. # #param absent_codes codes to use when an element is absent from a combination. For example, if you have TRANS;UNIT;UPPER you may want the code to be NNL when nothing is present.
  196. # @returns LIST_OUT a list of combinations
  197. # CODES_OUT a list of codes corresponding to each combination, with N meaning the item is not present, and the first letter of the list item meaning it is presen
  198. function(AllCombinations list_in absent_codes_in)
  199. list(LENGTH list_in list_count)
  200. set(num_combos 1)
  201. # subtract 1 since we will iterate from 0 to num_combos
  202. math(EXPR num_combos "(${num_combos} << ${list_count}) - 1")
  203. set(LIST_OUT "")
  204. set(CODES_OUT "")
  205. foreach (c RANGE 0 ${num_combos})
  206. set(current_combo "")
  207. set(current_code "")
  208. # this is a little ridiculous just to iterate through a list w/ indices
  209. math(EXPR last_list_index "${list_count} - 1")
  210. foreach (list_index RANGE 0 ${last_list_index})
  211. math(EXPR bit "1 << ${list_index}")
  212. math(EXPR combo_has_bit "${c} & ${bit}")
  213. list(GET list_in ${list_index} list_elem)
  214. if (combo_has_bit)
  215. if (current_combo)
  216. set(current_combo "${current_combo}:${list_elem}")
  217. else ()
  218. set(current_combo ${list_elem})
  219. endif ()
  220. string(SUBSTRING ${list_elem} 0 1 code_char)
  221. else ()
  222. list(GET absent_codes_in ${list_index} code_char)
  223. endif ()
  224. set(current_code "${current_code}${code_char}")
  225. endforeach ()
  226. if (current_combo STREQUAL "")
  227. list(APPEND LIST_OUT " ") # Empty set is a valid combination, but CMake isn't appending the empty string for some reason, use a space
  228. else ()
  229. list(APPEND LIST_OUT ${current_combo})
  230. endif ()
  231. list(APPEND CODES_OUT ${current_code})
  232. endforeach ()
  233. set(LIST_OUT ${LIST_OUT} PARENT_SCOPE)
  234. set(CODES_OUT ${CODES_OUT} PARENT_SCOPE)
  235. endfunction ()
  236. # generates object files for each of the sources, using the BLAS naming scheme to pass the function name as a preprocessor definition
  237. # @param sources_in the source files to build from
  238. # @param defines_in (optional) preprocessor definitions that will be applied to all objects
  239. # @param name_in (optional) if this is set this name will be used instead of the filename. Use a * to indicate where the float character should go, if no star the character will be prepended.
  240. # e.g. with DOUBLE set, "i*max" will generate the name "idmax", and "max" will be "dmax"
  241. # @param replace_last_with replaces the last character in the filename with this string (e.g. symm_k should be symm_TU)
  242. # @param append_with appends the filename with this string (e.g. trmm_R should be trmm_RTUU or some other combination of characters)
  243. # @param no_float_type turns off the float type define for this build (e.g. SINGLE/DOUBLE/etc)
  244. # @param complex_filename_scheme some routines have separate source files for complex and non-complex float types.
  245. # 0 - compiles for all types
  246. # 1 - compiles the sources for non-complex types only (SINGLE/DOUBLE)
  247. # 2 - compiles for complex types only (COMPLEX/DOUBLE COMPLEX)
  248. # 3 - compiles for all types, but changes source names for complex by prepending z (e.g. axpy.c becomes zaxpy.c)
  249. # 4 - compiles for complex types only, but changes source names for complex by prepending z (e.g. hemv.c becomes zhemv.c)
  250. # STRING - compiles only the given type (e.g. DOUBLE)
  251. function(GenerateNamedObjects sources_in)
  252. if (${ARGC} GREATER 1)
  253. set(defines_in ${ARGV1})
  254. endif ()
  255. if (${ARGC} GREATER 2 AND NOT "${ARGV2}" STREQUAL "")
  256. set(name_in ${ARGV2})
  257. # strip off extension for kernel files that pass in the object name.
  258. get_filename_component(name_in ${name_in} NAME_WE)
  259. endif ()
  260. if (${ARGC} GREATER 3)
  261. set(use_cblas ${ARGV3})
  262. else ()
  263. set(use_cblas false)
  264. endif ()
  265. if (${ARGC} GREATER 4)
  266. set(replace_last_with ${ARGV4})
  267. endif ()
  268. if (${ARGC} GREATER 5)
  269. set(append_with ${ARGV5})
  270. endif ()
  271. if (${ARGC} GREATER 6)
  272. set(no_float_type ${ARGV6})
  273. else ()
  274. set(no_float_type false)
  275. endif ()
  276. if (no_float_type)
  277. set(float_list "DUMMY") # still need to loop once
  278. else ()
  279. set(float_list "${FLOAT_TYPES}")
  280. endif ()
  281. set(real_only false)
  282. set(complex_only false)
  283. set(mangle_complex_sources false)
  284. if (${ARGC} GREATER 7 AND NOT "${ARGV7}" STREQUAL "")
  285. if (${ARGV7} EQUAL 1)
  286. set(real_only true)
  287. elseif (${ARGV7} EQUAL 2)
  288. set(complex_only true)
  289. elseif (${ARGV7} EQUAL 3)
  290. set(mangle_complex_sources true)
  291. elseif (${ARGV7} EQUAL 4)
  292. set(mangle_complex_sources true)
  293. set(complex_only true)
  294. elseif (NOT ${ARGV7} EQUAL 0)
  295. set(float_list ${ARGV7})
  296. endif ()
  297. endif ()
  298. if (complex_only)
  299. list(REMOVE_ITEM float_list "SINGLE")
  300. list(REMOVE_ITEM float_list "DOUBLE")
  301. list(REMOVE_ITEM float_list "BFLOAT16")
  302. elseif (real_only)
  303. list(REMOVE_ITEM float_list "COMPLEX")
  304. list(REMOVE_ITEM float_list "ZCOMPLEX")
  305. endif ()
  306. set(float_char "")
  307. set(OBJ_LIST_OUT "")
  308. foreach (float_type ${float_list})
  309. foreach (source_file ${sources_in})
  310. if (NOT no_float_type)
  311. string(SUBSTRING ${float_type} 0 1 float_char)
  312. string(TOLOWER ${float_char} float_char)
  313. if (${float_type} STREQUAL "BFLOAT16")
  314. set (float_char "sb")
  315. endif ()
  316. endif ()
  317. if (NOT name_in)
  318. get_filename_component(source_name ${source_file} NAME_WE)
  319. set(obj_name "${float_char}${source_name}")
  320. else ()
  321. # replace * with float_char
  322. if (${name_in} MATCHES "\\*")
  323. string(REPLACE "*" ${float_char} obj_name ${name_in})
  324. else ()
  325. set(obj_name "${float_char}${name_in}")
  326. endif ()
  327. endif ()
  328. if (replace_last_with)
  329. string(REGEX REPLACE ".$" ${replace_last_with} obj_name ${obj_name})
  330. else ()
  331. set(obj_name "${obj_name}${append_with}")
  332. endif ()
  333. # now add the object and set the defines
  334. set(obj_defines ${defines_in})
  335. list(FIND obj_defines "RC" def_idx)
  336. if (${def_idx} GREATER -1)
  337. # list(REMOVE_AT ${obj_defines} ${def_idx})
  338. list (REMOVE_ITEM obj_defines "RC")
  339. list(APPEND obj_defines "RC=RC")
  340. endif ()
  341. list(FIND obj_defines "CR" def_idx)
  342. if (${def_idx} GREATER -1)
  343. # list(REMOVE_AT ${obj_defines} ${def_idx})
  344. list (REMOVE_ITEM obj_defines "CR")
  345. list(APPEND obj_defines "CR=CR")
  346. endif ()
  347. if (use_cblas)
  348. set(obj_name "cblas_${obj_name}")
  349. list(APPEND obj_defines "CBLAS")
  350. elseif (NOT "${obj_name}" MATCHES "${ARCH_SUFFIX}")
  351. set(obj_name "${obj_name}${ARCH_SUFFIX}")
  352. endif ()
  353. list(APPEND obj_defines "ASMNAME=${FU}${obj_name};ASMFNAME=${FU}${obj_name}${BU};NAME=${obj_name}${BU};CNAME=${obj_name};CHAR_NAME=\"${obj_name}${BU}\";CHAR_CNAME=\"${obj_name}\"")
  354. if (${float_type} STREQUAL "DOUBLE" OR ${float_type} STREQUAL "ZCOMPLEX")
  355. list(APPEND obj_defines "DOUBLE")
  356. endif ()
  357. if (${float_type} STREQUAL "BFLOAT16")
  358. list(APPEND obj_defines "BFLOAT16")
  359. endif ()
  360. if (${float_type} STREQUAL "COMPLEX" OR ${float_type} STREQUAL "ZCOMPLEX")
  361. list(APPEND obj_defines "COMPLEX")
  362. if (mangle_complex_sources)
  363. # add a z to the filename
  364. get_filename_component(source_name ${source_file} NAME)
  365. get_filename_component(source_dir ${source_file} DIRECTORY)
  366. string(REPLACE ${source_name} "z${source_name}" source_file ${source_file})
  367. endif ()
  368. endif ()
  369. if (VERBOSE_GEN)
  370. message(STATUS "${obj_name}:${source_file}")
  371. message(STATUS "${obj_defines}")
  372. endif ()
  373. # create a copy of the source to avoid duplicate obj filename problem with ar.exe
  374. get_filename_component(source_extension ${source_file} EXT)
  375. set(new_source_file "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${obj_name}${source_extension}")
  376. if (IS_ABSOLUTE ${source_file})
  377. set(old_source_file ${source_file})
  378. else ()
  379. set(old_source_file "${CMAKE_CURRENT_LIST_DIR}/${source_file}")
  380. endif ()
  381. string(REPLACE ";" "\n#define " define_source "${obj_defines}")
  382. string(REPLACE "=" " " define_source "${define_source}")
  383. file(WRITE ${new_source_file}.tmp "#define ${define_source}\n#include \"${old_source_file}\"")
  384. configure_file(${new_source_file}.tmp ${new_source_file} COPYONLY)
  385. file(REMOVE ${new_source_file}.tmp)
  386. list(APPEND SRC_LIST_OUT ${new_source_file})
  387. message (STATUS ${new_source_file})
  388. if (DEFINED HAVE_FMA3)
  389. if ( ${new_source_file} MATCHES "(s|d?)rot_k.*c")
  390. set_source_files_properties(${new_source_file} PROPERTIES COMPILE_OPTIONS "-mfma")
  391. endif ()
  392. if ( ${new_source_file} MATCHES "dgemv_t_k.*c")
  393. set_source_files_properties(${new_source_file} PROPERTIES COMPILE_OPTIONS "-mfma")
  394. endif ()
  395. endif ()
  396. endforeach ()
  397. endforeach ()
  398. list(APPEND OPENBLAS_SRC ${SRC_LIST_OUT})
  399. set(OPENBLAS_SRC ${OPENBLAS_SRC} PARENT_SCOPE)
  400. endfunction ()
  401. # generates object files for each of the sources for each of the combinations of the preprocessor definitions passed in
  402. # @param sources_in the source files to build from
  403. # @param defines_in the preprocessor definitions that will be combined to create the object files
  404. # @param all_defines_in (optional) preprocessor definitions that will be applied to all objects
  405. # @param replace_scheme If 1, replace the "k" in the filename with the define combo letters. E.g. symm_k.c with TRANS and UNIT defined will be symm_TU.
  406. # If 0, it will simply append the code, e.g. symm_L.c with TRANS and UNIT will be symm_LTU.
  407. # If 2, it will append the code with an underscore, e.g. symm.c with TRANS and UNIT will be symm_TU.
  408. # If 3, it will insert the code *around* the last character with an underscore, e.g. symm_L.c with TRANS and UNIT will be symm_TLU (required by BLAS level2 objects).
  409. # If 4, it will insert the code before the last underscore. E.g. trtri_U_parallel with TRANS will be trtri_UT_parallel
  410. # @param alternate_name replaces the source name as the object name (define codes are still appended)
  411. # @param no_float_type turns off the float type define for this build (e.g. SINGLE/DOUBLE/etc)
  412. # @param complex_filename_scheme see GenerateNamedObjects
  413. function(GenerateCombinationObjects sources_in defines_in absent_codes_in all_defines_in replace_scheme)
  414. set(alternate_name_in "")
  415. if (${ARGC} GREATER 5)
  416. set(alternate_name_in ${ARGV5})
  417. endif ()
  418. set(no_float_type false)
  419. if (${ARGC} GREATER 6)
  420. set(no_float_type ${ARGV6})
  421. endif ()
  422. set(complex_filename_scheme "")
  423. if (${ARGC} GREATER 7)
  424. set(complex_filename_scheme ${ARGV7})
  425. endif ()
  426. AllCombinations("${defines_in}" "${absent_codes_in}")
  427. set(define_combos ${LIST_OUT})
  428. set(define_codes ${CODES_OUT})
  429. list(LENGTH define_combos num_combos)
  430. math(EXPR num_combos "${num_combos} - 1")
  431. foreach (c RANGE 0 ${num_combos})
  432. list(GET define_combos ${c} define_combo)
  433. list(GET define_codes ${c} define_code)
  434. foreach (source_file ${sources_in})
  435. set(alternate_name ${alternate_name_in})
  436. # replace colon separated list with semicolons, this turns it into a CMake list that we can use foreach with
  437. string(REPLACE ":" ";" define_combo ${define_combo})
  438. # now add the object and set the defines
  439. set(cur_defines ${define_combo})
  440. if ("${cur_defines}" STREQUAL " ")
  441. set(cur_defines ${all_defines_in})
  442. else ()
  443. list(APPEND cur_defines ${all_defines_in})
  444. endif ()
  445. set(replace_code "")
  446. set(append_code "")
  447. if (replace_scheme EQUAL 1)
  448. set(replace_code ${define_code})
  449. else ()
  450. if (replace_scheme EQUAL 2)
  451. set(append_code "_${define_code}")
  452. elseif (replace_scheme EQUAL 3)
  453. if ("${alternate_name}" STREQUAL "")
  454. string(REGEX MATCH "[a-zA-Z]\\." last_letter ${source_file})
  455. else ()
  456. string(REGEX MATCH "[a-zA-Z]$" last_letter ${alternate_name})
  457. endif ()
  458. # first extract the last letter
  459. string(SUBSTRING ${last_letter} 0 1 last_letter) # remove period from match
  460. # break the code up into the first letter and the remaining (should only be 2 anyway)
  461. string(SUBSTRING ${define_code} 0 1 define_code_first)
  462. string(SUBSTRING ${define_code} 1 -1 define_code_second)
  463. set(replace_code "${define_code_first}${last_letter}${define_code_second}")
  464. elseif (replace_scheme EQUAL 4)
  465. # insert code before the last underscore and pass that in as the alternate_name
  466. if ("${alternate_name}" STREQUAL "")
  467. get_filename_component(alternate_name ${source_file} NAME_WE)
  468. endif ()
  469. set(extra_underscore "")
  470. # check if filename has two underscores, insert another if not (e.g. getrs_parallel needs to become getrs_U_parallel not getrsU_parallel)
  471. string(REGEX MATCH "_[a-zA-Z]+_" underscores ${alternate_name})
  472. string(LENGTH "${underscores}" underscores)
  473. if (underscores EQUAL 0)
  474. set(extra_underscore "_")
  475. endif ()
  476. string(REGEX REPLACE "(.+)(_[^_]+)$" "\\1${extra_underscore}${define_code}\\2" alternate_name ${alternate_name})
  477. else()
  478. set(append_code ${define_code}) # replace_scheme should be 0
  479. endif ()
  480. endif ()
  481. GenerateNamedObjects("${source_file}" "${cur_defines}" "${alternate_name}" false "${replace_code}" "${append_code}" "${no_float_type}" "${complex_filename_scheme}")
  482. endforeach ()
  483. endforeach ()
  484. set(OPENBLAS_SRC ${OPENBLAS_SRC} PARENT_SCOPE)
  485. endfunction ()