cmake.bbclass 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. # Path to the CMake file to process.
  2. OECMAKE_SOURCEPATH ??= "${S}"
  3. DEPENDS_prepend = "cmake-native "
  4. B = "${WORKDIR}/build"
  5. # What CMake generator to use.
  6. # The supported options are "Unix Makefiles" or "Ninja".
  7. OECMAKE_GENERATOR ?= "Ninja"
  8. python() {
  9. generator = d.getVar("OECMAKE_GENERATOR")
  10. if "Unix Makefiles" in generator:
  11. args = "-G '" + generator + "' -DCMAKE_MAKE_PROGRAM=" + d.getVar("MAKE")
  12. d.setVar("OECMAKE_GENERATOR_ARGS", args)
  13. d.setVarFlag("do_compile", "progress", "percent")
  14. elif "Ninja" in generator:
  15. args = "-G '" + generator + "' -DCMAKE_MAKE_PROGRAM=ninja"
  16. d.appendVar("DEPENDS", " ninja-native")
  17. d.setVar("OECMAKE_GENERATOR_ARGS", args)
  18. d.setVarFlag("do_compile", "progress", r"outof:^\[(\d+)/(\d+)\]\s+")
  19. else:
  20. bb.fatal("Unknown CMake Generator %s" % generator)
  21. }
  22. OECMAKE_AR ?= "${AR}"
  23. # Compiler flags
  24. OECMAKE_C_FLAGS ?= "${HOST_CC_ARCH} ${TOOLCHAIN_OPTIONS} ${CFLAGS}"
  25. OECMAKE_CXX_FLAGS ?= "${HOST_CC_ARCH} ${TOOLCHAIN_OPTIONS} ${CXXFLAGS}"
  26. OECMAKE_C_FLAGS_RELEASE ?= "-DNDEBUG"
  27. OECMAKE_CXX_FLAGS_RELEASE ?= "-DNDEBUG"
  28. OECMAKE_C_LINK_FLAGS ?= "${HOST_CC_ARCH} ${TOOLCHAIN_OPTIONS} ${CPPFLAGS} ${LDFLAGS}"
  29. OECMAKE_CXX_LINK_FLAGS ?= "${HOST_CC_ARCH} ${TOOLCHAIN_OPTIONS} ${CXXFLAGS} ${LDFLAGS}"
  30. CXXFLAGS += "${HOST_CC_ARCH} ${TOOLCHAIN_OPTIONS}"
  31. CFLAGS += "${HOST_CC_ARCH} ${TOOLCHAIN_OPTIONS}"
  32. def oecmake_map_compiler(compiler, d):
  33. args = d.getVar(compiler).split()
  34. if args[0] == "ccache":
  35. return args[1], args[0]
  36. return args[0], ""
  37. # C/C++ Compiler (without cpu arch/tune arguments)
  38. OECMAKE_C_COMPILER ?= "${@oecmake_map_compiler('CC', d)[0]}"
  39. OECMAKE_C_COMPILER_LAUNCHER ?= "${@oecmake_map_compiler('CC', d)[1]}"
  40. OECMAKE_CXX_COMPILER ?= "${@oecmake_map_compiler('CXX', d)[0]}"
  41. OECMAKE_CXX_COMPILER_LAUNCHER ?= "${@oecmake_map_compiler('CXX', d)[1]}"
  42. # clear compiler vars for allarch to avoid sig hash difference
  43. OECMAKE_C_COMPILER_allarch = ""
  44. OECMAKE_C_COMPILER_LAUNCHER_allarch = ""
  45. OECMAKE_CXX_COMPILER_allarch = ""
  46. OECMAKE_CXX_COMPILER_LAUNCHER_allarch = ""
  47. OECMAKE_RPATH ?= ""
  48. OECMAKE_PERLNATIVE_DIR ??= ""
  49. OECMAKE_EXTRA_ROOT_PATH ?= ""
  50. OECMAKE_FIND_ROOT_PATH_MODE_PROGRAM = "ONLY"
  51. OECMAKE_FIND_ROOT_PATH_MODE_PROGRAM_class-native = "BOTH"
  52. EXTRA_OECMAKE_append = " ${PACKAGECONFIG_CONFARGS}"
  53. export CMAKE_BUILD_PARALLEL_LEVEL
  54. CMAKE_BUILD_PARALLEL_LEVEL_task-compile = "${@oe.utils.parallel_make(d, False)}"
  55. CMAKE_BUILD_PARALLEL_LEVEL_task-install = "${@oe.utils.parallel_make(d, True)}"
  56. OECMAKE_TARGET_COMPILE ?= "all"
  57. OECMAKE_TARGET_INSTALL ?= "install"
  58. def map_host_os_to_system_name(host_os):
  59. if host_os.startswith('mingw'):
  60. return 'Windows'
  61. if host_os.startswith('linux'):
  62. return 'Linux'
  63. return host_os
  64. # CMake expects target architectures in the format of uname(2),
  65. # which do not always match TARGET_ARCH, so all the necessary
  66. # conversions should happen here.
  67. def map_host_arch_to_uname_arch(host_arch):
  68. if host_arch == "powerpc":
  69. return "ppc"
  70. if host_arch == "powerpc64":
  71. return "ppc64"
  72. return host_arch
  73. cmake_do_generate_toolchain_file() {
  74. if [ "${BUILD_SYS}" = "${HOST_SYS}" ]; then
  75. cmake_crosscompiling="set( CMAKE_CROSSCOMPILING FALSE )"
  76. fi
  77. cat > ${WORKDIR}/toolchain.cmake <<EOF
  78. # CMake system name must be something like "Linux".
  79. # This is important for cross-compiling.
  80. $cmake_crosscompiling
  81. set( CMAKE_SYSTEM_NAME ${@map_host_os_to_system_name(d.getVar('HOST_OS'))} )
  82. set( CMAKE_SYSTEM_PROCESSOR ${@map_host_arch_to_uname_arch(d.getVar('HOST_ARCH'))} )
  83. set( CMAKE_C_COMPILER ${OECMAKE_C_COMPILER} )
  84. set( CMAKE_CXX_COMPILER ${OECMAKE_CXX_COMPILER} )
  85. set( CMAKE_C_COMPILER_LAUNCHER ${OECMAKE_C_COMPILER_LAUNCHER} )
  86. set( CMAKE_CXX_COMPILER_LAUNCHER ${OECMAKE_CXX_COMPILER_LAUNCHER} )
  87. set( CMAKE_ASM_COMPILER ${OECMAKE_C_COMPILER} )
  88. set( CMAKE_AR ${OECMAKE_AR} CACHE FILEPATH "Archiver" )
  89. set( CMAKE_C_FLAGS "${OECMAKE_C_FLAGS}" CACHE STRING "CFLAGS" )
  90. set( CMAKE_CXX_FLAGS "${OECMAKE_CXX_FLAGS}" CACHE STRING "CXXFLAGS" )
  91. set( CMAKE_ASM_FLAGS "${OECMAKE_C_FLAGS}" CACHE STRING "ASM FLAGS" )
  92. set( CMAKE_C_FLAGS_RELEASE "${OECMAKE_C_FLAGS_RELEASE}" CACHE STRING "Additional CFLAGS for release" )
  93. set( CMAKE_CXX_FLAGS_RELEASE "${OECMAKE_CXX_FLAGS_RELEASE}" CACHE STRING "Additional CXXFLAGS for release" )
  94. set( CMAKE_ASM_FLAGS_RELEASE "${OECMAKE_C_FLAGS_RELEASE}" CACHE STRING "Additional ASM FLAGS for release" )
  95. set( CMAKE_C_LINK_FLAGS "${OECMAKE_C_LINK_FLAGS}" CACHE STRING "LDFLAGS" )
  96. set( CMAKE_CXX_LINK_FLAGS "${OECMAKE_CXX_LINK_FLAGS}" CACHE STRING "LDFLAGS" )
  97. # only search in the paths provided so cmake doesnt pick
  98. # up libraries and tools from the native build machine
  99. set( CMAKE_FIND_ROOT_PATH ${STAGING_DIR_HOST} ${STAGING_DIR_NATIVE} ${CROSS_DIR} ${OECMAKE_PERLNATIVE_DIR} ${OECMAKE_EXTRA_ROOT_PATH} ${EXTERNAL_TOOLCHAIN} ${HOSTTOOLS_DIR})
  100. set( CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY )
  101. set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ${OECMAKE_FIND_ROOT_PATH_MODE_PROGRAM} )
  102. set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
  103. set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
  104. set( CMAKE_PROGRAM_PATH "/" )
  105. # Use qt.conf settings
  106. set( ENV{QT_CONF_PATH} ${WORKDIR}/qt.conf )
  107. # We need to set the rpath to the correct directory as cmake does not provide any
  108. # directory as rpath by default
  109. set( CMAKE_INSTALL_RPATH ${OECMAKE_RPATH} )
  110. # Use RPATHs relative to build directory for reproducibility
  111. set( CMAKE_BUILD_RPATH_USE_ORIGIN ON )
  112. # Use our cmake modules
  113. list(APPEND CMAKE_MODULE_PATH "${STAGING_DATADIR}/cmake/Modules/")
  114. # add for non /usr/lib libdir, e.g. /usr/lib64
  115. set( CMAKE_LIBRARY_PATH ${libdir} ${base_libdir})
  116. # add include dir to implicit includes in case it differs from /usr/include
  117. list(APPEND CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES ${includedir})
  118. list(APPEND CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES ${includedir})
  119. EOF
  120. }
  121. addtask generate_toolchain_file after do_patch before do_configure
  122. CONFIGURE_FILES = "CMakeLists.txt"
  123. cmake_do_configure() {
  124. if [ "${OECMAKE_BUILDPATH}" ]; then
  125. bbnote "cmake.bbclass no longer uses OECMAKE_BUILDPATH. The default behaviour is now out-of-tree builds with B=WORKDIR/build."
  126. fi
  127. if [ "${S}" != "${B}" ]; then
  128. rm -rf ${B}
  129. mkdir -p ${B}
  130. cd ${B}
  131. else
  132. find ${B} -name CMakeFiles -or -name Makefile -or -name cmake_install.cmake -or -name CMakeCache.txt -delete
  133. fi
  134. # Just like autotools cmake can use a site file to cache result that need generated binaries to run
  135. if [ -e ${WORKDIR}/site-file.cmake ] ; then
  136. oecmake_sitefile="-C ${WORKDIR}/site-file.cmake"
  137. else
  138. oecmake_sitefile=
  139. fi
  140. cmake \
  141. ${OECMAKE_GENERATOR_ARGS} \
  142. $oecmake_sitefile \
  143. ${OECMAKE_SOURCEPATH} \
  144. -DCMAKE_INSTALL_PREFIX:PATH=${prefix} \
  145. -DCMAKE_INSTALL_BINDIR:PATH=${@os.path.relpath(d.getVar('bindir'), d.getVar('prefix') + '/')} \
  146. -DCMAKE_INSTALL_SBINDIR:PATH=${@os.path.relpath(d.getVar('sbindir'), d.getVar('prefix') + '/')} \
  147. -DCMAKE_INSTALL_LIBEXECDIR:PATH=${@os.path.relpath(d.getVar('libexecdir'), d.getVar('prefix') + '/')} \
  148. -DCMAKE_INSTALL_SYSCONFDIR:PATH=${sysconfdir} \
  149. -DCMAKE_INSTALL_SHAREDSTATEDIR:PATH=${@os.path.relpath(d.getVar('sharedstatedir'), d. getVar('prefix') + '/')} \
  150. -DCMAKE_INSTALL_LOCALSTATEDIR:PATH=${localstatedir} \
  151. -DCMAKE_INSTALL_LIBDIR:PATH=${@os.path.relpath(d.getVar('libdir'), d.getVar('prefix') + '/')} \
  152. -DCMAKE_INSTALL_INCLUDEDIR:PATH=${@os.path.relpath(d.getVar('includedir'), d.getVar('prefix') + '/')} \
  153. -DCMAKE_INSTALL_DATAROOTDIR:PATH=${@os.path.relpath(d.getVar('datadir'), d.getVar('prefix') + '/')} \
  154. -DPYTHON_EXECUTABLE:PATH=${PYTHON} \
  155. -DPython_EXECUTABLE:PATH=${PYTHON} \
  156. -DPython3_EXECUTABLE:PATH=${PYTHON} \
  157. -DLIB_SUFFIX=${@d.getVar('baselib').replace('lib', '')} \
  158. -DCMAKE_INSTALL_SO_NO_EXE=0 \
  159. -DCMAKE_TOOLCHAIN_FILE=${WORKDIR}/toolchain.cmake \
  160. -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 \
  161. ${EXTRA_OECMAKE} \
  162. -Wno-dev
  163. }
  164. # To disable verbose cmake logs for a given recipe or globally config metadata e.g. local.conf
  165. # add following
  166. #
  167. # CMAKE_VERBOSE = ""
  168. #
  169. CMAKE_VERBOSE ??= "VERBOSE=1"
  170. # Then run do_compile again
  171. cmake_runcmake_build() {
  172. bbnote ${DESTDIR:+DESTDIR=${DESTDIR} }${CMAKE_VERBOSE} cmake --build '${B}' "$@" -- ${EXTRA_OECMAKE_BUILD}
  173. eval ${DESTDIR:+DESTDIR=${DESTDIR} }${CMAKE_VERBOSE} cmake --build '${B}' "$@" -- ${EXTRA_OECMAKE_BUILD}
  174. }
  175. cmake_do_compile() {
  176. cmake_runcmake_build --target ${OECMAKE_TARGET_COMPILE}
  177. }
  178. cmake_do_install() {
  179. DESTDIR='${D}' cmake_runcmake_build --target ${OECMAKE_TARGET_INSTALL}
  180. }
  181. EXPORT_FUNCTIONS do_configure do_compile do_install do_generate_toolchain_file