CMakeLists.txt 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #
  2. # Public Domain.
  3. #
  4. project(nacl C)
  5. cmake_minimum_required(VERSION 2.4)
  6. # Generic hook to allow arbitrary cmake code to be run for preconfiguration.
  7. # to pass assert that ARM NEON is available:
  8. # set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -mfpu=neon")
  9. if(CNACL_CONFIG_SCRIPT)
  10. include(${CNACL_CONFIG_SCRIPT})
  11. endif()
  12. file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include")
  13. file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/include_internal")
  14. add_subdirectory(randombytes)
  15. if(CMAKE_VERSION VERSION_LESS 2.8.4)
  16. message("Parallel building (-j) will not be available.")
  17. message("To build in parallel, upgrade to cmake 2.8.4 or newer.")
  18. message("see: http://www.cmake.org/Bug/print_bug_page.php?bug_id=10395")
  19. endif()
  20. #################################
  21. enable_language(ASM)
  22. set(CMAKE_ASM_COMPILER_ARG1 "${MY_CMAKE_ASM_FLAGS} -c")
  23. macro(print appendTo content)
  24. list(APPEND ${appendTo} "${content}\n")
  25. endmacro()
  26. ##
  27. # Create a header file for an operation/primitive such as crypto_stream/salsa20.
  28. # NOTE: Not all primitives are required to behave the same for a given operation.
  29. # crypto_stream/salsa20 will obviously give you a different output
  30. # than crypto_stream/aes128ctr.
  31. #
  32. # @param operation the operation name, a generic name for the job which is done.
  33. # @param primitive the name of the algorithm which is used to do the operation.
  34. # @param output the name of a variable which will be set to a string containing the header file.
  35. ##
  36. function(writeOperationHeader operation primitive output)
  37. set(op "${operation}_${primitive}")
  38. set(out "")
  39. print(out "#ifndef ${operation}_H")
  40. print(out "#define ${operation}_H")
  41. print(out "")
  42. print(out "#include \"${op}.h\"")
  43. print(out "")
  44. foreach(macro ${MACROS})
  45. if("${macro}" MATCHES "${operation}$|${operation}\\(|${operation}_")
  46. string(REGEX REPLACE "${operation}" "${op}" regexout "${macro}")
  47. print( out "#define ${macro} ${regexout}")
  48. endif()
  49. endforeach()
  50. print(out "#define ${operation}_PRIMITIVE \"${primitive}\"")
  51. print(out "#define ${operation}_IMPLEMENTATION ${op}_IMPLEMENTATION")
  52. print(out "#define ${operation}_VERSION ${op}_VERSION")
  53. print(out "")
  54. print(out "#endif")
  55. string(REGEX REPLACE "\n;" "\n" tmpoutStr "${out}")
  56. set(${output} ${tmpoutStr} PARENT_SCOPE)
  57. endfunction()
  58. ##
  59. # Create a header file for an operation/primitive/implementation
  60. # such as crypto_stream/salsa20/amd64_xmm.
  61. # This is a (potentially processor specific) implementation of an operation/primitive.
  62. # All implementations must return the same output for a given input.
  63. #
  64. # @param operation the operation name, a generic name for the job which is done.
  65. # @param primitive the name of the algorithm which is used to do the operation.
  66. # @param implementation the name of the implementation of the operation/primitive.
  67. # @param output the name of a variable which will be set to a string containing the header file.
  68. ##
  69. function(writeOperationPrimitiveHeader operation primitive implementation output)
  70. set(op "${operation}_${primitive}")
  71. set(path "${operation}/${primitive}/${implementation}")
  72. string(REGEX REPLACE "[\\.-/]" "_" opi "${path}")
  73. set(tmpout "")
  74. print(tmpout "#ifndef ${op}_H")
  75. print(tmpout "#define ${op}_H")
  76. print(tmpout "")
  77. file(STRINGS "${CMAKE_SOURCE_DIR}/${path}/api.h" api)
  78. foreach(line ${api})
  79. string(REGEX REPLACE "[ \\t]CRYPTO_" " ${opi}_" out "${line}")
  80. print(tmpout "${out}")
  81. endforeach()
  82. # C++
  83. print(tmpout "#ifdef __cplusplus")
  84. print(tmpout "#include <string>")
  85. foreach(prototype ${PROTOTYPES_CPP})
  86. if("${prototype}" MATCHES "${operation}$|${operation}\\(|${operation}_")
  87. string(REGEX REPLACE "${operation}" "${opi}" out "${prototype}")
  88. print(tmpout "${out}")
  89. endif()
  90. endforeach()
  91. print(tmpout "extern \"C\" {")
  92. print(tmpout "#endif")
  93. # C
  94. foreach(prototype ${PROTOTYPES})
  95. if("${prototype}" MATCHES "${operation}$|${operation}\\(|${operation}_")
  96. string(REGEX REPLACE "${operation}" "${opi}" out "${prototype}")
  97. print(tmpout "${out}")
  98. endif()
  99. endforeach()
  100. print(tmpout "#ifdef __cplusplus")
  101. print(tmpout "}")
  102. print(tmpout "#endif")
  103. foreach(macro ${MACROS})
  104. if("${macro}" MATCHES "${operation}$|${operation}\\(|${operation}_")
  105. string(REGEX REPLACE "${operation}" "${opi}" mopi "${macro}")
  106. string(REGEX REPLACE "${operation}" "${op}" mop "${macro}")
  107. print(tmpout "#define ${mop} ${mopi}")
  108. endif()
  109. endforeach()
  110. print(tmpout "#define ${op}_IMPLEMENTATION \"${path}\"")
  111. print(tmpout "#ifndef ${opi}_VERSION")
  112. print(tmpout "#define ${opi}_VERSION \"-\"")
  113. print(tmpout "#endif")
  114. print(tmpout "#define ${op}_VERSION ${opi}_VERSION")
  115. print(tmpout "")
  116. print(tmpout "#endif")
  117. string(REGEX REPLACE "\n;" "\n" tmpoutStr "${tmpout}")
  118. set(${output} ${tmpoutStr} PARENT_SCOPE)
  119. endfunction()
  120. function(doOperationPrimitiveImplementation
  121. operation
  122. primitive
  123. implementation
  124. allOpPrimitives
  125. runTest
  126. )
  127. #message("${operation} --- ${primitive} --- ${implementation}")
  128. #message("${allOpPrimitives}")
  129. set(opiPath "${operation}/${primitive}/${implementation}")
  130. file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/${opiPath}")
  131. writeOperationPrimitiveHeader("${operation}" "${primitive}" "${implementation}" output)
  132. file(WRITE "${CMAKE_BINARY_DIR}/include/${operation}_${primitive}.h" "${output}")
  133. file(GLOB files "${CMAKE_SOURCE_DIR}/${opiPath}/*.[csS]")
  134. set(lib "${operation}_${primitive}_${implementation}")
  135. print(tmpout "set(CMAKE_CURRENT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})")
  136. print(tmpout "include_directories(
  137. \"${CMAKE_BINARY_DIR}/${operation}/${primitive}\"
  138. \"${CMAKE_BINARY_DIR}/${opiPath}\"
  139. \"${CMAKE_BINARY_DIR}/include\"
  140. \"${CMAKE_BINARY_DIR}/include_internal\"
  141. )")
  142. print(tmpout "add_library(${lib} ${files})")
  143. print(tmpout "set_target_properties(${lib} PROPERTIES LINKER_LANGUAGE C)")
  144. string(REGEX REPLACE "\n;" "\n" tmpoutStr "${tmpout}")
  145. file(WRITE "${CMAKE_BINARY_DIR}/${opiPath}/CMakeLists.txt" "${tmpoutStr}")
  146. endfunction()
  147. function(executePlan implementations)
  148. set(opPrimitives "")
  149. foreach(line ${implementations})
  150. string(REGEX REPLACE "/[^/]*$" "" opSlashPrim ${line})
  151. string(REPLACE "/" "_" opPrim ${opSlashPrim})
  152. list(APPEND opPrimitives ${opPrim})
  153. endforeach()
  154. set(operations "")
  155. foreach(line ${implementations})
  156. string(REPLACE "/" ";" newLine ${line})
  157. list(GET newLine 0 op)
  158. list(GET newLine 1 prim)
  159. list(GET newLine 2 impl)
  160. doOperationPrimitiveImplementation(${op} ${prim} ${impl} "${opPrimitives}" FALSE)
  161. set("${op}_primitives"
  162. "${${op}_primitives};${prim}"
  163. CACHE INTERNAL "primitives by operation" FORCE
  164. )
  165. set("${op}_${prim}_implementations"
  166. "${${op}_${prim}_implementations};${impl}"
  167. CACHE INTERNAL "implementations by primitivie" FORCE
  168. )
  169. list(APPEND operations "${op}")
  170. endforeach()
  171. set(libraries "")
  172. cmake_policy(SET CMP0007 NEW)
  173. list(REMOVE_DUPLICATES operations)
  174. foreach(op ${operations})
  175. list(REMOVE_DUPLICATES ${op}_primitives)
  176. foreach(prim ${${op}_primitives})
  177. list(REMOVE_DUPLICATES ${op}_${prim}_implementations)
  178. #message("${op} ---- ${prim}")
  179. foreach(impl ${${op}_${prim}_implementations})
  180. #message("${op} === ${prim} === ${impl}")
  181. print(tmpout "add_subdirectory(${impl})")
  182. list(APPEND libraries "${op}_${prim}_${impl}")
  183. endforeach()
  184. string(REGEX REPLACE "\n;" "\n" tmpoutStr "${tmpout}")
  185. file(WRITE "${CMAKE_BINARY_DIR}/${op}/${prim}/CMakeLists.txt" "${tmpoutStr}")
  186. set(tmpout "")
  187. print(opOut "add_subdirectory(${prim})")
  188. writeOperationHeader("${op}" "${prim}" output)
  189. file(WRITE "${CMAKE_BINARY_DIR}/${op}/${prim}/${op}.h" "${output}")
  190. endforeach()
  191. string(REGEX REPLACE "\n;" "\n" tmpoutStr "${opOut}")
  192. file(WRITE "${CMAKE_BINARY_DIR}/${op}/CMakeLists.txt" "${tmpoutStr}")
  193. set(opOut "")
  194. add_subdirectory("${CMAKE_BINARY_DIR}/${op}" "${CMAKE_BINARY_DIR}/${op}")
  195. endforeach()
  196. include("${CMAKE_SOURCE_DIR}/cmake/libutils.cmake")
  197. merge_static_libs(nacl nacl "${libraries}")
  198. #add_dependencies(nacl randombytes)
  199. endFunction()
  200. function(writeTypesHeaders types)
  201. foreach(intfile
  202. "crypto_uint8.h"
  203. "crypto_int8.h"
  204. "crypto_uint16.h"
  205. "crypto_int26.h"
  206. "crypto_uint32.h"
  207. "crypto_int32.h"
  208. "crypto_uint64.h"
  209. "crypto_int64.h"
  210. )
  211. file(WRITE "${CMAKE_BINARY_DIR}/include_internal/${intfile}" "#include <crypto_types.h>")
  212. endforeach()
  213. set(out)
  214. print(out "#ifndef crypto_types_h")
  215. print(out "#define crypto_types_h")
  216. foreach(type ${types})
  217. print(out "${type};")
  218. endforeach()
  219. print(out "#endif")
  220. string(REGEX REPLACE "\n;" "\n" tmpoutStr "${out}")
  221. file(WRITE "${CMAKE_BINARY_DIR}/include/crypto_types.h" "${tmpoutStr}")
  222. endfunction()
  223. include("${CMAKE_SOURCE_DIR}/cmake/AbiName.cmake")
  224. AbiName_get(abi "${CMAKE_REQUIRED_FLAGS}")
  225. message("Detected ABI as ${abi}")
  226. set(planPath "${CMAKE_SOURCE_DIR}/cmake/plans/${abi}_plan.cmake")
  227. ## On apple systems, the assembler is different and it doesn't accept
  228. ## a number of the asm files in NaCl
  229. if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Darwin")
  230. set(planPath "${CMAKE_SOURCE_DIR}/cmake/plans/apple_${abi}_plan.cmake")
  231. endif()
  232. message("Using a [${CMAKE_HOST_SYSTEM_NAME}] toolchain.")
  233. if (NOT EXISTS "${planPath}")
  234. message("Could not find compile plan for this ABI, please wait while one is generated...")
  235. execute_process(COMMAND "${CMAKE_SOURCE_DIR}/do" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
  236. include("${CMAKE_SOURCE_DIR}/cmake/MakePlan.cmake")
  237. makePlan("${abi}" "${planPath}")
  238. if (NOT EXISTS "${planPath}")
  239. message("Can't find plan for the target ABI [${abi}].")
  240. message(FATAL_ERROR "Cross compiling is not supported without a premade plan.")
  241. endif()
  242. message("Created new plan for ${abi} at ${planPath}")
  243. file(READ "${planPath}" plan)
  244. message("${plan}")
  245. else()
  246. message("Using preexisting build plan ${planPath}")
  247. endif()
  248. include("${planPath}")
  249. writeTypesHeaders("${PLAN_TYPES}")
  250. file(STRINGS "${CMAKE_SOURCE_DIR}/MACROS" MACROS)
  251. file(STRINGS "${CMAKE_SOURCE_DIR}/PROTOTYPES.c" PROTOTYPES)
  252. file(STRINGS "${CMAKE_SOURCE_DIR}/PROTOTYPES.cpp" PROTOTYPES_CPP)
  253. file(STRINGS "${CMAKE_SOURCE_DIR}/OPERATIONS" OPERATIONS)
  254. executePlan("${PLAN_IMPLEMENTATIONS}")
  255. enable_testing()
  256. add_subdirectory(tests)