libutils.cmake 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. # Copyright (C) 2009 Sun Microsystems, Inc
  2. #
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; version 2 of the License.
  6. #
  7. # This program is distributed in the hope that it will be useful,
  8. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. # GNU General Public License for more details.
  11. #
  12. # You should have received a copy of the GNU General Public License
  13. # along with this program; if not, write to the Free Software
  14. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. # This file exports macros that emulate some functionality found in GNU libtool
  16. # on Unix systems. One such feature is convenience libraries. In this context,
  17. # convenience library is a static library that can be linked to shared library
  18. # On systems that force position-independent code, linking into shared library
  19. # normally requires compilation with a special flag (often -fPIC). To enable
  20. # linking static libraries to shared, we compile source files that come into
  21. # static library with the PIC flag (${CMAKE_SHARED_LIBRARY_C_FLAGS} in CMake)
  22. # Some systems, like Windows or OSX do not need special compilation (Windows
  23. # never uses PIC and OSX always uses it).
  24. #
  25. # The intention behind convenience libraries is simplify the build and to reduce
  26. # excessive recompiles.
  27. # Except for convenience libraries, this file provides macros to merge static
  28. # libraries (we need it for mysqlclient) and to create shared library out of
  29. # convenience libraries(again, for mysqlclient)
  30. # Following macros are exported
  31. # - ADD_CONVENIENCE_LIBRARY(target source1...sourceN)
  32. # This macro creates convenience library. The functionality is similar to
  33. # ADD_LIBRARY(target STATIC source1...sourceN), the difference is that resulting
  34. # library can always be linked to shared library
  35. #
  36. # - MERGE_LIBRARIES(target [STATIC|SHARED|MODULE] [linklib1 .... linklibN]
  37. # [EXPORTS exported_func1 .... exported_func_N]
  38. # [OUTPUT_NAME output_name]
  39. # This macro merges several static libraries into a single one or creates a shared
  40. # library from several convenience libraries
  41. # Important global flags
  42. # - WITH_PIC : If set, it is assumed that everything is compiled as position
  43. # independent code (that is CFLAGS/CMAKE_C_FLAGS contain -fPIC or equivalent)
  44. # If defined, ADD_CONVENIENCE_LIBRARY does not add PIC flag to compile flags
  45. #
  46. # - DISABLE_SHARED: If set, it is assumed that shared libraries are not produced
  47. # during the build. ADD_CONVENIENCE_LIBRARY does not add anything to compile flags
  48. GET_FILENAME_COMPONENT(MYSQL_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
  49. IF(WIN32 OR CYGWIN OR APPLE OR WITH_PIC OR DISABLE_SHARED OR NOT CMAKE_SHARED_LIBRARY_C_FLAGS)
  50. SET(_SKIP_PIC 1)
  51. ENDIF()
  52. INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/cmake_parse_arguments.cmake)
  53. # CREATE_EXPORT_FILE (VAR target api_functions)
  54. # Internal macro, used to create source file for shared libraries that
  55. # otherwise consists entirely of "convenience" libraries. On Windows,
  56. # also exports API functions as dllexport. On unix, creates a dummy file
  57. # that references all exports and this prevents linker from creating an
  58. # empty library(there are unportable alternatives, --whole-archive)
  59. MACRO(CREATE_EXPORT_FILE VAR TARGET API_FUNCTIONS)
  60. IF(WIN32)
  61. SET(DUMMY ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_dummy.c)
  62. SET(EXPORTS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_exports.def)
  63. CONFIGURE_FILE_CONTENT("" ${DUMMY})
  64. SET(CONTENT "EXPORTS\n")
  65. FOREACH(FUNC ${API_FUNCTIONS})
  66. SET(CONTENT "${CONTENT} ${FUNC}\n")
  67. ENDFOREACH()
  68. CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS})
  69. SET(${VAR} ${DUMMY} ${EXPORTS})
  70. ELSE()
  71. SET(EXPORTS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_exports_file.cc)
  72. SET(CONTENT)
  73. FOREACH(FUNC ${API_FUNCTIONS})
  74. SET(CONTENT "${CONTENT} extern void* ${FUNC}\;\n")
  75. ENDFOREACH()
  76. SET(CONTENT "${CONTENT} void *${TARGET}_api_funcs[] = {\n")
  77. FOREACH(FUNC ${API_FUNCTIONS})
  78. SET(CONTENT "${CONTENT} &${FUNC},\n")
  79. ENDFOREACH()
  80. SET(CONTENT "${CONTENT} (void *)0\n}\;")
  81. CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS})
  82. SET(${VAR} ${EXPORTS})
  83. ENDIF()
  84. ENDMACRO()
  85. # MYSQL_ADD_CONVENIENCE_LIBRARY(name source1...sourceN)
  86. # Create static library that can be linked to shared library.
  87. # On systems that force position-independent code, adds -fPIC or
  88. # equivalent flag to compile flags.
  89. MACRO(ADD_CONVENIENCE_LIBRARY)
  90. SET(TARGET ${ARGV0})
  91. SET(SOURCES ${ARGN})
  92. LIST(REMOVE_AT SOURCES 0)
  93. ADD_LIBRARY(${TARGET} STATIC ${SOURCES})
  94. IF(NOT _SKIP_PIC)
  95. SET_TARGET_PROPERTIES(${TARGET} PROPERTIES COMPILE_FLAGS
  96. "${CMAKE_SHARED_LIBRARY_C_FLAGS}")
  97. ENDIF()
  98. ENDMACRO()
  99. # Write content to file, using CONFIGURE_FILE
  100. # The advantage compared to FILE(WRITE) is that timestamp
  101. # does not change if file already has the same content
  102. MACRO(CONFIGURE_FILE_CONTENT content file)
  103. SET(CMAKE_CONFIGURABLE_FILE_CONTENT
  104. "${content}\n")
  105. CONFIGURE_FILE(
  106. ${MYSQL_CMAKE_SCRIPT_DIR}/configurable_file_content.in
  107. ${file}
  108. @ONLY)
  109. ENDMACRO()
  110. # Merge static libraries into a big static lib. The resulting library
  111. # should not not have dependencies on other static libraries.
  112. # We use it in MySQL to merge mysys,dbug,vio etc into mysqlclient
  113. MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE)
  114. # To produce a library we need at least one source file.
  115. # It is created by ADD_CUSTOM_COMMAND below and will helps
  116. # also help to track dependencies.
  117. SET(SOURCE_FILE ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_depends.c)
  118. ADD_LIBRARY(${TARGET} STATIC ${SOURCE_FILE})
  119. SET_TARGET_PROPERTIES(${TARGET} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME})
  120. SET(OSLIBS)
  121. FOREACH(LIB ${LIBS_TO_MERGE})
  122. GET_TARGET_PROPERTY(LIB_LOCATION ${LIB} LOCATION)
  123. GET_TARGET_PROPERTY(LIB_TYPE ${LIB} TYPE)
  124. IF(NOT LIB_LOCATION)
  125. # 3rd party library like libz.so. Make sure that everything
  126. # that links to our library links to this one as well.
  127. LIST(APPEND OSLIBS ${LIB})
  128. ELSE()
  129. # This is a target in current project
  130. # (can be a static or shared lib)
  131. IF(LIB_TYPE STREQUAL "STATIC_LIBRARY")
  132. SET(STATIC_LIBS ${STATIC_LIBS} ${LIB_LOCATION})
  133. ADD_DEPENDENCIES(${TARGET} ${LIB})
  134. # Extract dependend OS libraries
  135. GET_DEPENDEND_OS_LIBS(${LIB} LIB_OSLIBS)
  136. LIST(APPEND OSLIBS ${LIB_OSLIBS})
  137. ELSE()
  138. # This is a shared library our static lib depends on.
  139. LIST(APPEND OSLIBS ${LIB})
  140. ENDIF()
  141. ENDIF()
  142. ENDFOREACH()
  143. IF(OSLIBS)
  144. LIST(REMOVE_DUPLICATES OSLIBS)
  145. TARGET_LINK_LIBRARIES(${TARGET} ${OSLIBS})
  146. ENDIF()
  147. # Make the generated dummy source file depended on all static input
  148. # libs. If input lib changes,the source file is touched
  149. # which causes the desired effect (relink).
  150. ADD_CUSTOM_COMMAND(
  151. OUTPUT ${SOURCE_FILE}
  152. COMMAND ${CMAKE_COMMAND} -E touch ${SOURCE_FILE}
  153. DEPENDS ${STATIC_LIBS})
  154. IF(MSVC)
  155. # To merge libs, just pass them to lib.exe command line.
  156. SET(LINKER_EXTRA_FLAGS "")
  157. FOREACH(LIB ${STATIC_LIBS})
  158. SET(LINKER_EXTRA_FLAGS "${LINKER_EXTRA_FLAGS} ${LIB}")
  159. ENDFOREACH()
  160. SET_TARGET_PROPERTIES(${TARGET} PROPERTIES STATIC_LIBRARY_FLAGS
  161. "${LINKER_EXTRA_FLAGS}")
  162. ELSE()
  163. GET_TARGET_PROPERTY(TARGET_LOCATION ${TARGET} LOCATION)
  164. IF(APPLE)
  165. # Use OSX's libtool to merge archives (ihandles universal
  166. # binaries properly)
  167. ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD
  168. COMMAND rm ${TARGET_LOCATION}
  169. COMMAND /usr/bin/libtool -static -o ${TARGET_LOCATION}
  170. ${STATIC_LIBS}
  171. )
  172. ELSE()
  173. # Generic Unix, Cygwin or MinGW. In post-build step, call
  174. # script, that extracts objects from archives with "ar x"
  175. # and repacks them with "ar r"
  176. SET(TARGET ${TARGET})
  177. CONFIGURE_FILE(
  178. ${MYSQL_CMAKE_SCRIPT_DIR}/merge_archives_unix.cmake.in
  179. ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}.cmake
  180. @ONLY
  181. )
  182. ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD
  183. COMMAND rm ${TARGET_LOCATION}
  184. COMMAND ${CMAKE_COMMAND} -P
  185. ${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}.cmake
  186. )
  187. ENDIF()
  188. ENDIF()
  189. ENDMACRO()
  190. # Create libs from libs.
  191. # Merges static libraries, creates shared libraries out of convenience libraries.
  192. # MERGE_LIBRARIES(target [STATIC|SHARED|MODULE]
  193. # [linklib1 .... linklibN]
  194. # [EXPORTS exported_func1 .... exportedFuncN]
  195. # [OUTPUT_NAME output_name]
  196. #)
  197. MACRO(MERGE_LIBRARIES)
  198. CMAKE_PARSE_ARGUMENTS(ARG
  199. "EXPORTS;OUTPUT_NAME"
  200. "STATIC;SHARED;MODULE;NOINSTALL"
  201. ${ARGN}
  202. )
  203. LIST(GET ARG_DEFAULT_ARGS 0 TARGET)
  204. SET(LIBS ${ARG_DEFAULT_ARGS})
  205. LIST(REMOVE_AT LIBS 0)
  206. IF(ARG_STATIC)
  207. IF (NOT ARG_OUTPUT_NAME)
  208. SET(ARG_OUTPUT_NAME ${TARGET})
  209. ENDIF()
  210. MERGE_STATIC_LIBS(${TARGET} ${ARG_OUTPUT_NAME} "${LIBS}")
  211. ELSEIF(ARG_SHARED OR ARG_MODULE)
  212. IF(ARG_SHARED)
  213. SET(LIBTYPE SHARED)
  214. ELSE()
  215. SET(LIBTYPE MODULE)
  216. ENDIF()
  217. # check for non-PIC libraries
  218. IF(NOT _SKIP_PIC)
  219. FOREACH(LIB ${LIBS})
  220. GET_TARGET_PROPERTY(${LIB} TYPE LIBTYPE)
  221. IF(LIBTYPE STREQUAL "STATIC_LIBRARY")
  222. GET_TARGET_PROPERTY(LIB COMPILE_FLAGS LIB_COMPILE_FLAGS)
  223. STRING(REPLACE "${CMAKE_SHARED_LIBRARY_C_FLAGS}"
  224. "<PIC_FLAG>" LIB_COMPILE_FLAGS ${LIB_COMPILE_FLAG})
  225. IF(NOT LIB_COMPILE_FLAGS MATCHES "<PIC_FLAG>")
  226. MESSAGE(FATAL_ERROR
  227. "Attempted to link non-PIC static library ${LIB} to shared library ${TARGET}\n"
  228. "Please use ADD_CONVENIENCE_LIBRARY, instead of ADD_LIBRARY for ${LIB}"
  229. )
  230. ENDIF()
  231. ENDIF()
  232. ENDFOREACH()
  233. ENDIF()
  234. CREATE_EXPORT_FILE(SRC ${TARGET} "${ARG_EXPORTS}")
  235. ADD_LIBRARY(${TARGET} ${LIBTYPE} ${SRC})
  236. TARGET_LINK_LIBRARIES(${TARGET} ${LIBS})
  237. IF(ARG_OUTPUT_NAME)
  238. SET_TARGET_PROPERTIES(${TARGET} PROPERTIES OUTPUT_NAME "${ARG_OUTPUT_NAME}")
  239. ENDIF()
  240. ELSE()
  241. MESSAGE(FATAL_ERROR "Unknown library type")
  242. ENDIF()
  243. IF(NOT ARG_NOINSTALL)
  244. MYSQL_INSTALL_TARGETS(${TARGET} DESTINATION "${INSTALL_LIBDIR}")
  245. ENDIF()
  246. SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_INTERFACE_LIBRARIES "")
  247. ENDMACRO()
  248. FUNCTION(GET_DEPENDEND_OS_LIBS target result)
  249. SET(deps ${${target}_LIB_DEPENDS})
  250. IF(deps)
  251. FOREACH(lib ${deps})
  252. # Filter out keywords for used for debug vs optimized builds
  253. IF(NOT lib MATCHES "general" AND NOT lib MATCHES "debug" AND NOT lib MATCHES "optimized")
  254. GET_TARGET_PROPERTY(lib_location ${lib} LOCATION)
  255. IF(NOT lib_location)
  256. SET(ret ${ret} ${lib})
  257. ENDIF()
  258. ENDIF()
  259. ENDFOREACH()
  260. ENDIF()
  261. SET(${result} ${ret} PARENT_SCOPE)
  262. ENDFUNCTION()
  263. MACRO(RESTRICT_SYMBOL_EXPORTS target)
  264. IF(CMAKE_COMPILER_IS_GNUCXX AND UNIX)
  265. CHECK_C_COMPILER_FLAG("-fvisibility=hidden" HAVE_VISIBILITY_HIDDEN)
  266. IF(HAVE_VISIBILITY_HIDDEN)
  267. GET_TARGET_PROPERTY(COMPILE_FLAGS ${target} COMPILE_FLAGS)
  268. IF(NOT COMPILE_FLAGS)
  269. # Avoid COMPILE_FLAGS-NOTFOUND
  270. SET(COMPILE_FLAGS)
  271. ENDIF()
  272. SET_TARGET_PROPERTIES(${target} PROPERTIES
  273. COMPILE_FLAGS "${COMPILE_FLAGS} -fvisibility=hidden")
  274. ENDIF()
  275. ENDIF()
  276. ENDMACRO()