GenKernel.cmake 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #
  2. # Several function to generate Linux kernel Makefile
  3. #
  4. # global variable used:
  5. # LINUX_KERNEL_BUILD_DIR - used by GenKernel_addTarget to find the KBuild
  6. #
  7. # functions:
  8. # GenSpaceList()
  9. # GenKernel_Makefile()
  10. # GenKernel_Kconfig()
  11. # GenKernel_addTarget()
  12. #
  13. # e.g. of usage
  14. # set(KO_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/mantis_kn.c)
  15. # set(KO_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/kn)
  16. #
  17. # if (NOT DEFINED LINUX_KERNEL_BUILD_DIR)
  18. # execute_process(COMMAND uname -r OUTPUT_VARIABLE KERNEL_VER OUTPUT_STRIP_TRAILING_WHITESPACE)
  19. # set (LINUX_KERNEL_BUILD_DIR "/lib/modules/${KERNEL_VER}/build")
  20. # message ("LINUX_KERNEL_BUILD_DIR not define: using kernel ${KERNEL_VER}")
  21. # endif()
  22. #
  23. # get_directory_property(KO_INCLUDES INCLUDE_DIRECTORIES)
  24. # GenSpaceList("${KO_INCLUDES}" "-I" KO_INCLUDES)
  25. # get_directory_property(KO_CFLAGS DEFINITIONS) # spaces and -D
  26. #
  27. # GenKernel_Makefile(${MANTISLIB_NAME} "${KO_CFLAGS}" "${KO_SOURCES}" "${KO_INCLUDES}" ${KO_BINARY_DIR} ${KO_MODE})
  28. # GenKernel_addTarget(${MANTISLIB_NAME}_KO ${KO_BINARY_DIR})
  29. if(NOT DEFINED GENKERN_PREFIX)
  30. # set MANTISLIB_PREFIX to directory where the current file file is located
  31. get_filename_component(GENKERN_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
  32. endif()
  33. #
  34. # Transform a cmake list (; separated) into space separated with a prefix (e.g. -I)
  35. #
  36. function(GenSpaceList LIST PREFIX PARENT_SCOPE_LIST_NAME)
  37. set (TMP)
  38. foreach(v ${LIST})
  39. set (TMP "${TMP} ${PREFIX}${v}")
  40. endforeach()
  41. set (${PARENT_SCOPE_LIST_NAME} ${TMP} PARENT_SCOPE)
  42. endfunction()
  43. #
  44. # Generate a kernel module Makefile usable with Kbuild
  45. #
  46. # KO_MODULE_NAME is the name of the kernel target
  47. # KO_CFLAGS list of cflags as a string with -D and separated with spaces - protected with "${LIST}"
  48. # KO_INCLUDES list of includes as string with -I and separated with spaces - protected with "${LIST}"
  49. # KO_SOURCES is a list of files (normal CMake list work) to compile for the module - protected with "${LIST}"
  50. # WARNING: the path must be global (use CMAKE_CURRENT_SOURCE_DIR, see example above)
  51. # KO_OUTDIR is the place where all C files will be copied and the Makefile generated
  52. # KO_MODE is the mode for kernel compilation, "m" for module "y" for built-in
  53. #
  54. # Note you can use GenSpaceList and get_directory_property to get the spaced lists:
  55. # e.g.
  56. # get_directory_property(KO_INCLUDES INCLUDE_DIRECTORIES)
  57. # GenSpaceList("${KO_INCLUDES}" "-I" KO_INCLUDES)
  58. #
  59. function(GenKernel_Makefile KO_MODULE_NAME KO_CFLAGS KO_SOURCES KO_INCLUDES KO_OUTDIR KO_MODE)
  60. if (NOT EXISTS ${KO_OUTDIR})
  61. file(MAKE_DIRECTORY ${KO_OUTDIR})
  62. endif()
  63. if (NOT EXISTS ${KO_OUTDIR}/include)
  64. file(MAKE_DIRECTORY ${KO_OUTDIR}/include)
  65. endif()
  66. set(TO_CLEAN
  67. ${KO_OUTDIR}/${KO_MODULE_NAME}.ko
  68. ${KO_OUTDIR}/${KO_MODULE_NAME}.o
  69. ${KO_OUTDIR}/${KO_MODULE_NAME}.mod.c
  70. ${KO_OUTDIR}/${KO_MODULE_NAME}.mod.o
  71. ${KO_OUTDIR}/modules.order
  72. ${KO_OUTDIR}/Module.symvers
  73. ${KO_OUTDIR}/built-in.o
  74. )
  75. set (KO_LOCAL_INCLUDES "-I\$(src)/include")
  76. set (KO_INCLUDES "${KO_INCLUDES} ${KO_LOCAL_INCLUDES}")
  77. set (TMP) # reset
  78. foreach(file ${KO_SOURCES})
  79. # copy file to local dir - c files in local, h files in ./include
  80. # extract filename without extention
  81. get_filename_component (filename ${file} NAME)
  82. #
  83. get_filename_component (extension ${file} EXT)
  84. # for a module called MyMod.ko a file MyMod.c is needed to define the point of entry
  85. # and other things but shouldn't be in the sources
  86. if (${extension} MATCHES ".c" )
  87. get_filename_component (filename_we ${file} NAME_WE)
  88. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${file} ${KO_OUTDIR}/${filename})
  89. set (TMP "${TMP} ${filename_we}.o")
  90. set (TO_CLEAN ${TO_CLEAN} ${KO_OUTDIR}/${filename_we}.o)
  91. elseif (${extension} MATCHES ".h")
  92. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${file} ${KO_OUTDIR}/include/${filename})
  93. elseif(IS_DIRECTORY ${file})
  94. file(GLOB files ${file}/*) # get files AND directories underneath
  95. if (DEBUG_MODULES)
  96. message("process ${file}")
  97. endif()
  98. foreach(elem ${files})
  99. get_filename_component(filen ${elem} NAME)
  100. get_filename_component(ext ${elem} EXT)
  101. if ( ${ext} MATCHES ".h" OR IS_DIRECTORY ${elem} )
  102. if (DEBUG_MODULES)
  103. message(" link ${filen}")
  104. endif()
  105. execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${elem} ${KO_OUTDIR}/include/${filen})
  106. endif()
  107. endforeach()
  108. else()
  109. message ("unknown extension for file ${file}")
  110. endif()
  111. endforeach()
  112. set (KO_SOURCES ${TMP})
  113. message (STATUS "generating ${KO_OUTDIR}/Makefile")
  114. configure_file(${GENKERN_PREFIX}/kernel_makefile.cmakein ${KO_OUTDIR}/Makefile)
  115. if(${KO_MODE} MATCHES "y")
  116. # generate an additional makefile for module building
  117. set(KO_MODE "m")
  118. configure_file(${GENKERN_PREFIX}/kernel_makefile.cmakein ${KO_OUTDIR}/Makefile_module)
  119. else()
  120. # generate an additional makefile for static building
  121. set(KO_MODE "y")
  122. configure_file(${GENKERN_PREFIX}/kernel_makefile.cmakein ${KO_OUTDIR}/Makefile_static)
  123. endif()
  124. set(KO_INCLUDES ${KO_LOCAL_INCLUDES}) # empty for gpl makefile but local includes
  125. configure_file(${GENKERN_PREFIX}/kernel_makefile.cmakein ${KO_OUTDIR}/Makefile_gpl)
  126. set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${TO_CLEAN}")
  127. endfunction()
  128. #
  129. # Generate a simple Kconfig file - this is experimental
  130. #
  131. # KO_MODULE_NAME
  132. # KO_BUILD_MODULE - if yes set the KO_BUILD to tristate (kernel module, inside kernel or not built) if no set to bool (inside kernel or not built)
  133. # KO_BRIEF - brief description of the module
  134. # KO_DEFAULT - default mode (y for inside kernel, m for module - if KO_BUILD_MODULE=YES - or n for not built)
  135. # KO_HELP - description of the module
  136. # KO_OUTDIR
  137. # KO_DEPENDS - string that defines the dependencies e.g. "depends on V4L && !DMA"
  138. #
  139. function(GenKernel_Kconfig KO_MODULE_NAME KO_BUILD_MODULE KO_BRIEF KO_BUILD_DEFAULT KO_HELP KO_OUTDIR KO_DEPENDS)
  140. if (NOT EXISTS ${KO_OUTDIR})
  141. file(MAKE_DIRECTORY ${KO_OUTDIR})
  142. endif()
  143. set(KO_DEFAULT "n")
  144. if (KO_BUILD_MODULE)
  145. set(KO_BUILD "tristate")
  146. if (${KO_BUILD_DEFAULT})
  147. set(KO_DEFAULT "m")
  148. endif()
  149. else()
  150. set(KO_BUILD "bool")
  151. if (${KO_BUILD_DEFAULT})
  152. set(KO_DEFAULT "y")
  153. endif()
  154. endif()
  155. set(KO_EXTRA ${KO_DEPENDS})
  156. message (STATUS "generating ${KO_OUTDIR}/Kconfig")
  157. configure_file(${GENKERN_PREFIX}/kernel_kconfig.cmakein ${KO_OUTDIR}/Kconfig)
  158. endfunction()
  159. #
  160. # Add custom target ${KO_MODULE_NAME}
  161. #
  162. # KO_MODULE_NAME is the name of the kernel target
  163. # KO_OUTDIR is the place where all C files will be copied and the Makefile generated
  164. #
  165. # Uses a globally defined LINUX_KERNEL_BUILD_DIR that is the directory your kernel is in
  166. #
  167. function(GenKernel_addTarget KO_MODULE_NAME KO_OUTDIR)
  168. if(NOT DEFINED LINUX_KERNEL_BUILD_DIR)
  169. message(FATAL_ERROR "LINUX_KERNEL_BUILD_DIR should be defined")
  170. endif()
  171. add_custom_target(${KO_MODULE_NAME} ALL
  172. COMMAND MAKEFLAGS= ${CMAKE_MAKE_PROGRAM} -C ${LINUX_KERNEL_BUILD_DIR} M=${KO_OUTDIR} modules
  173. WORKING_DIRECTORY ${KO_OUTDIR}
  174. COMMENT "Building the kernel module: ${KO_MODULE_NAME}"
  175. )
  176. endfunction()
  177. #
  178. # Add custom target ${KO_MODULE_NAME}
  179. #
  180. # KO_MODULE_NAME is the name of the kernel target
  181. # KO_OPT additional option to give to make when building the KO
  182. # KO_OUTDIR is the place where all C files will be copied and the Makefile generated
  183. #
  184. # Uses a globally defined LINUX_KERNEL_BUILD_DIR that is the directory your kernel is in
  185. #
  186. function(GenKernel_addSpecialTarget KO_MODULE_NAME KO_OPT KO_OUTDIR)
  187. if(NOT DEFINED LINUX_KERNEL_BUILD_DIR)
  188. message(FATAL_ERROR "LINUX_KERNEL_BUILD_DIR should be defined")
  189. endif()
  190. add_custom_target(${KO_MODULE_NAME} ALL
  191. COMMAND MAKEFLAGS= ${CMAKE_MAKE_PROGRAM} -C ${LINUX_KERNEL_BUILD_DIR} ${KO_OPT} M=${KO_OUTDIR} modules
  192. WORKING_DIRECTORY ${KO_OUTDIR}
  193. COMMENT "Building the kernel module: ${KO_MODULE_NAME}"
  194. )
  195. endfunction()