CheckPrototypeDefinition.cmake 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file LICENSE.rst or https://cmake.org/licensing for details.
  3. #[=======================================================================[.rst:
  4. CheckPrototypeDefinition
  5. ------------------------
  6. Check if a ``C`` function has the expected prototype.
  7. .. command:: check_prototype_definition
  8. .. code-block:: cmake
  9. check_prototype_definition(<function> <prototype> <return> <headers> <variable>)
  10. ``<function>``
  11. The name of the function whose prototype is being checked.
  12. ``<prototype>``
  13. The expected prototype of the function, provided as a string.
  14. ``<return>``
  15. The return value of the function. This will be used as a return value in
  16. the function definition body of the generated test program to verify that
  17. the function's return type matches the expected type.
  18. ``<headers>``
  19. A :ref:`semicolon-separated list <CMake Language Lists>` of header file
  20. names required for checking the function prototype.
  21. ``<variable>``
  22. The name of the variable to store the check result. This variable will be
  23. created as an internal cache variable.
  24. This command generates a test program and verifies that it builds without
  25. errors. The generated test program includes specified ``<headers>``, defines
  26. a function with given literal ``<prototype>`` and ``<return>`` value and
  27. then uses the specified ``<function>``. The simplified test program can be
  28. illustrated as:
  29. .. code-block:: c
  30. #include <headers>
  31. // ...
  32. <prototype> { return <return>; }
  33. int main(...) { ...<function>()... }
  34. The following variables may be set before calling this function to modify
  35. the way the check is run:
  36. .. include:: /module/include/CMAKE_REQUIRED_FLAGS.rst
  37. .. include:: /module/include/CMAKE_REQUIRED_DEFINITIONS.rst
  38. .. include:: /module/include/CMAKE_REQUIRED_INCLUDES.rst
  39. .. include:: /module/include/CMAKE_REQUIRED_LINK_OPTIONS.rst
  40. .. include:: /module/include/CMAKE_REQUIRED_LIBRARIES.rst
  41. .. include:: /module/include/CMAKE_REQUIRED_LINK_DIRECTORIES.rst
  42. .. include:: /module/include/CMAKE_REQUIRED_QUIET.rst
  43. Examples
  44. ^^^^^^^^
  45. Checking if the ``getpwent_r()`` function on Solaris/illumos systems has the
  46. expected prototype:
  47. .. code-block:: cmake
  48. include(CheckPrototypeDefinition)
  49. check_prototype_definition(
  50. getpwent_r
  51. "struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)"
  52. "NULL"
  53. "unistd.h;pwd.h"
  54. HAVE_SOLARIS_GETPWENT_R
  55. )
  56. #]=======================================================================]
  57. #
  58. get_filename_component(__check_proto_def_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
  59. include_guard(GLOBAL)
  60. function(check_prototype_definition _FUNCTION _PROTOTYPE _RETURN _HEADER _VARIABLE)
  61. if (NOT DEFINED ${_VARIABLE})
  62. if(NOT CMAKE_REQUIRED_QUIET)
  63. message(CHECK_START "Checking prototype ${_FUNCTION} for ${_VARIABLE}")
  64. endif()
  65. set(CHECK_PROTOTYPE_DEFINITION_CONTENT "/* */\n")
  66. set(CHECK_PROTOTYPE_DEFINITION_FLAGS ${CMAKE_REQUIRED_FLAGS})
  67. if (CMAKE_REQUIRED_LINK_OPTIONS)
  68. set(CHECK_PROTOTYPE_DEFINITION_LINK_OPTIONS
  69. LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
  70. else()
  71. set(CHECK_PROTOTYPE_DEFINITION_LINK_OPTIONS)
  72. endif()
  73. if (CMAKE_REQUIRED_LIBRARIES)
  74. set(CHECK_PROTOTYPE_DEFINITION_LIBS
  75. LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
  76. else()
  77. set(CHECK_PROTOTYPE_DEFINITION_LIBS)
  78. endif()
  79. if (CMAKE_REQUIRED_INCLUDES)
  80. set(CMAKE_SYMBOL_EXISTS_INCLUDES
  81. "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
  82. else()
  83. set(CMAKE_SYMBOL_EXISTS_INCLUDES)
  84. endif()
  85. if(CMAKE_REQUIRED_LINK_DIRECTORIES)
  86. set(_CPD_LINK_DIRECTORIES
  87. "-DLINK_DIRECTORIES:STRING=${CMAKE_REQUIRED_LINK_DIRECTORIES}")
  88. else()
  89. set(_CPD_LINK_DIRECTORIES)
  90. endif()
  91. foreach(_FILE ${_HEADER})
  92. string(APPEND CHECK_PROTOTYPE_DEFINITION_HEADER
  93. "#include <${_FILE}>\n")
  94. endforeach()
  95. set(CHECK_PROTOTYPE_DEFINITION_SYMBOL ${_FUNCTION})
  96. set(CHECK_PROTOTYPE_DEFINITION_PROTO ${_PROTOTYPE})
  97. set(CHECK_PROTOTYPE_DEFINITION_RETURN ${_RETURN})
  98. file(READ ${__check_proto_def_dir}/CheckPrototypeDefinition.c.in _SOURCE)
  99. string(CONFIGURE "${_SOURCE}" _SOURCE @ONLY)
  100. try_compile(${_VARIABLE}
  101. SOURCE_FROM_VAR CheckPrototypeDefinition.c _SOURCE
  102. COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
  103. ${CHECK_PROTOTYPE_DEFINITION_LINK_OPTIONS}
  104. ${CHECK_PROTOTYPE_DEFINITION_LIBS}
  105. CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${CHECK_PROTOTYPE_DEFINITION_FLAGS}
  106. "${CMAKE_SYMBOL_EXISTS_INCLUDES}"
  107. "${_CPD_LINK_DIRECTORIES}"
  108. )
  109. unset(_CPD_LINK_DIRECTORIES)
  110. if (${_VARIABLE})
  111. set(${_VARIABLE} 1 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
  112. if(NOT CMAKE_REQUIRED_QUIET)
  113. message(CHECK_PASS "True")
  114. endif()
  115. else ()
  116. if(NOT CMAKE_REQUIRED_QUIET)
  117. message(CHECK_FAIL "False")
  118. endif()
  119. set(${_VARIABLE} 0 CACHE INTERNAL "Have correct prototype for ${_FUNCTION}")
  120. endif ()
  121. endif()
  122. endfunction()