PackageConfig.cmake 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. # Filename: PackageConfig.cmake
  2. #
  3. # This module defines functions which find and configure libraries
  4. # and packages for Panda3D.
  5. #
  6. # Assumes an attempt to find the package has already been made with
  7. # find_package(). (i.e. relies on packagename_FOUND variable)
  8. #
  9. # Function: package_option
  10. # Usage:
  11. # package_option(package_name package_doc_string
  12. # [DEFAULT ON | OFF]
  13. # [FOUND_AS find_name]
  14. # [LICENSE license])
  15. # Examples:
  16. # package_option(LIBNAME "Enables LIBNAME support." DEFAULT OFF)
  17. #
  18. # If no default is given, the default in normal
  19. # builds is to enable all found third-party packages.
  20. # In builds for redistribution, there is the additional requirement that
  21. # the package be suitably-licensed.
  22. #
  23. # FOUND_AS indicates the name of the CMake find_package() module, which
  24. # may differ from Panda3D's internal name for that package.
  25. #
  26. #
  27. # Function: config_package
  28. # Usage:
  29. # config_package(package_name "Package description" ["Config summary"])
  30. # Examples:
  31. # config_package(OpenAL "OpenAL Audio Output")
  32. # config_package(ROCKET "Rocket" "without Python bindings")
  33. #
  34. #
  35. # Function: show_packages
  36. # Usage:
  37. # show_packages()
  38. #
  39. # This prints the package usage report using the information provided in
  40. # calls to config_package above.
  41. #
  42. #
  43. # Function: target_use_packages
  44. # Usage:
  45. # target_use_packages(target [PACKAGES ...])
  46. # Examples:
  47. # target_use_packages(mylib PYTHON PNG)
  48. #
  49. #
  50. # package_option
  51. #
  52. # In order to make sure no third-party licenses are inadvertently violated,
  53. # this imposes a few rules regarding license:
  54. # 1) If there is no license, no special restrictions.
  55. # 2) If there is a license, but the build is not flagged for redistribution,
  56. # no special restrictions.
  57. # 3) If there is a license, and this is for redistribution, the package is
  58. # forcibly defaulted off and must be explicitly enabled, unless the license
  59. # matches a list of licenses suitable for redistribution.
  60. #
  61. function(package_option name)
  62. # Parse the arguments.
  63. set(command)
  64. set(default)
  65. set(found_as "${name}")
  66. set(license "")
  67. set(cache_string)
  68. foreach(arg ${ARGN})
  69. if(command STREQUAL "DEFAULT")
  70. set(default "${arg}")
  71. set(command)
  72. elseif(command STREQUAL "FOUND_AS")
  73. set(found_as "${arg}")
  74. set(command)
  75. elseif(command STREQUAL "LICENSE")
  76. set(license "${arg}")
  77. set(command)
  78. elseif(arg STREQUAL "DEFAULT")
  79. set(command "DEFAULT")
  80. elseif(arg STREQUAL "FOUND_AS")
  81. set(command "FOUND_AS")
  82. elseif(arg STREQUAL "LICENSE")
  83. set(command "LICENSE")
  84. else()
  85. # Yes, a list, because semicolons can be in there, and
  86. # that gets split up into multiple args, so we have to
  87. # join it back together here.
  88. list(APPEND cache_string "${arg}")
  89. endif()
  90. endforeach()
  91. if(command STREQUAL "DEFAULT")
  92. message(SEND_ERROR "DEFAULT in package_option takes an argument")
  93. endif()
  94. # If the default is not set, we set it.
  95. if(NOT DEFINED default)
  96. if(IS_DIST_BUILD)
  97. # Accept things that don't have a configured license
  98. if(license STREQUAL "")
  99. set(default "${${found_as}_FOUND}")
  100. else()
  101. list(FIND PANDA_DIST_USE_LICENSES ${license} license_index)
  102. # If the license isn't in the accept listed, don't use the package
  103. message("INDEX for ${name}: ${license_index}")
  104. if(${license_index} EQUAL "-1")
  105. set(default OFF)
  106. else()
  107. set(default "${${found_as}_FOUND}")
  108. endif()
  109. endif()
  110. elseif(IS_MINSIZE_BUILD)
  111. set(default OFF)
  112. else()
  113. set(default "${${found_as}_FOUND}")
  114. endif()
  115. endif()
  116. # If it was set by the user but not found, display an error.
  117. if(HAVE_${name} AND NOT ${found_as}_FOUND)
  118. message(SEND_ERROR "NOT FOUND: ${name}. Disable HAVE_${name} to continue.")
  119. endif()
  120. # Prevent the function from being called twice.
  121. # This would indicate a cmake error.
  122. if(PANDA_DID_SET_OPTION_${name})
  123. message(SEND_ERROR "package_option(${name}) was called twice.
  124. This is a bug in the cmake build scripts.")
  125. else()
  126. set(PANDA_DID_SET_OPTION_${name} TRUE PARENT_SCOPE)
  127. endif()
  128. set(PANDA_PACKAGE_DEFAULT_${name} "${default}" PARENT_SCOPE)
  129. # Create the option.
  130. option("HAVE_${name}" "${cache_string}" "${default}")
  131. if(HAVE_${name})
  132. set(_${name}_INCLUDES ${${found_as}_INCLUDE_DIRS} ${${found_as}_INCLUDE_DIR}
  133. CACHE INTERNAL "<Internal>")
  134. if(${found_as}_LIBRARIES)
  135. set(_${name}_LIBRARIES ${${found_as}_LIBRARIES} CACHE INTERNAL "<Internal>")
  136. else()
  137. set(_${name}_LIBRARIES "${${found_as}_LIBRARY}" CACHE INTERNAL "<Internal>")
  138. endif()
  139. else()
  140. unset(_${name}_INCLUDES CACHE)
  141. unset(_${name}_LIBRARIES CACHE)
  142. endif()
  143. endfunction()
  144. set(_ALL_CONFIG_PACKAGES CACHE INTERNAL "Internal variable")
  145. #
  146. # config_package
  147. #
  148. function(config_package name desc)
  149. set(note "")
  150. foreach(arg ${ARGN})
  151. set(note "${arg}")
  152. endforeach()
  153. if(NOT PANDA_DID_SET_OPTION_${name})
  154. message(SEND_ERROR "config_package(${name}) was called before package_option(${name}).
  155. This is a bug in the cmake build scripts.")
  156. endif()
  157. list(FIND _ALL_CONFIG_PACKAGES "${name}" called_twice)
  158. if(called_twice GREATER -1)
  159. message(SEND_ERROR "config_package(${name}) was called twice.
  160. This is a bug in the cmake build scripts.")
  161. else()
  162. list(APPEND _ALL_CONFIG_PACKAGES "${name}")
  163. set(_ALL_CONFIG_PACKAGES "${_ALL_CONFIG_PACKAGES}" CACHE INTERNAL "Internal variable")
  164. endif()
  165. set(PANDA_PACKAGE_DESC_${name} "${desc}" PARENT_SCOPE)
  166. set(PANDA_PACKAGE_NOTE_${name} "${note}" PARENT_SCOPE)
  167. endfunction()
  168. #
  169. # show_packages
  170. #
  171. function(show_packages)
  172. message("")
  173. message("Configuring support for the following optional third-party packages:")
  174. foreach(package ${_ALL_CONFIG_PACKAGES})
  175. set(desc "${PANDA_PACKAGE_DESC_${package}}")
  176. set(note "${PANDA_PACKAGE_NOTE_${package}}")
  177. if(HAVE_${package})
  178. if(NOT note STREQUAL "")
  179. message("+ ${desc} (${note})")
  180. else()
  181. message("+ ${desc}")
  182. endif()
  183. else()
  184. if(NOT ${package}_FOUND)
  185. set(reason "not found")
  186. elseif(NOT PANDA_PACKAGE_DEFAULT_${package})
  187. set(reason "not requested")
  188. else()
  189. set(reason "disabled")
  190. endif()
  191. message("- ${desc} (${reason})")
  192. endif()
  193. endforeach()
  194. endfunction()
  195. #
  196. # target_use_packages
  197. #
  198. # Useful macro that picks up a package located using find_package
  199. # as dependencies of a target that is going to be built.
  200. #
  201. macro(target_use_packages target)
  202. set(libs ${ARGV})
  203. list(REMOVE_AT libs 0)
  204. foreach(lib ${libs})
  205. if(HAVE_${lib})
  206. target_link_libraries("${target}" ${_${lib}_LIBRARIES})
  207. # This is gross, but we actually want to hide package include directories
  208. # from Interrogate to make sure it relies on parser-inc instead, so we'll
  209. # use some generator expressions to do that.
  210. target_include_directories("${target}" PUBLIC
  211. $<$<NOT:$<BOOL:$<TARGET_PROPERTY:IS_INTERROGATE>>>:${_${lib}_INCLUDES}>)
  212. endif()
  213. endforeach(lib)
  214. endmacro(target_use_packages)