1# Copyright (c) 2009, 2021, Oracle and/or its affiliates. 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, version 2.0, 5# as published by the Free Software Foundation. 6# 7# This program is also distributed with certain software (including 8# but not limited to OpenSSL) that is licensed under separate terms, 9# as designated in a particular file or component or in included license 10# documentation. The authors of MySQL hereby grant you an additional 11# permission to link the program and your derivative works with the 12# separately licensed software that they have included with MySQL. 13# 14# This program is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17# GNU General Public License, version 2.0, for more details. 18# 19# You should have received a copy of the GNU General Public License 20# along with this program; if not, write to the Free Software 21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 23 24# This file exports macros that emulate some functionality found in GNU libtool 25# on Unix systems. One such feature is convenience libraries. In this context, 26# convenience library is a static library that can be linked to shared library 27# On systems that force position-independent code, linking into shared library 28# normally requires compilation with a special flag (often -fPIC). To enable 29# linking static libraries to shared, we compile source files that come into 30# static library with the PIC flag (${CMAKE_SHARED_LIBRARY_C_FLAGS} in CMake) 31# Some systems, like Windows or OSX do not need special compilation (Windows 32# never uses PIC and OSX always uses it). 33# 34# The intention behind convenience libraries is simplify the build and to reduce 35# excessive recompiles. 36 37# Except for convenience libraries, this file provides macros to merge static 38# libraries (we need it for mysqlclient) and to create shared library out of 39# convenience libraries(again, for mysqlclient) 40 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 49 50GET_FILENAME_COMPONENT(MYSQL_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH) 51IF(WIN32 OR APPLE OR WITH_PIC OR DISABLE_SHARED OR NOT CMAKE_SHARED_LIBRARY_C_FLAGS) 52 SET(_SKIP_PIC 1) 53ENDIF() 54 55INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/cmake_parse_arguments.cmake) 56# CREATE_EXPORT_FILE (VAR target api_functions) 57# Internal macro, used on Windows to export API functions as dllexport. 58# Returns a list of extra files that should be linked into the library 59# (in the variable pointed to by VAR). 60MACRO(CREATE_EXPORT_FILE VAR TARGET API_FUNCTIONS) 61 SET(DUMMY ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_dummy.cc) 62 CONFIGURE_FILE_CONTENT("" ${DUMMY}) 63 IF(WIN32) 64 SET(EXPORTS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_exports.def) 65 SET(CONTENT "EXPORTS\n") 66 FOREACH(FUNC ${API_FUNCTIONS}) 67 SET(CONTENT "${CONTENT} ${FUNC}\n") 68 ENDFOREACH() 69 CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS}) 70 SET(${VAR} ${DUMMY} ${EXPORTS}) 71 ELSE() 72 SET(${VAR} ${DUMMY}) 73 ENDIF() 74ENDMACRO() 75 76 77# ADD_CONVENIENCE_LIBRARY(name source1...sourceN) 78# Create static library that can be merged with other libraries. 79# On systems that force position-independent code, adds -fPIC or 80# equivalent flag to compile flags. 81MACRO(ADD_CONVENIENCE_LIBRARY) 82 SET(TARGET ${ARGV0}) 83 SET(SOURCES ${ARGN}) 84 LIST(REMOVE_AT SOURCES 0) 85 ADD_LIBRARY(${TARGET} STATIC ${SOURCES}) 86 IF(NOT _SKIP_PIC) 87 SET_TARGET_PROPERTIES(${TARGET} PROPERTIES POSITION_INDEPENDENT_CODE ON) 88 ENDIF() 89 90 # Collect all static libraries in the same directory 91 SET_TARGET_PROPERTIES(${TARGET} PROPERTIES 92 ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/archive_output_directory) 93 94 # Keep track of known convenience libraries, in a global scope. 95 SET(KNOWN_CONVENIENCE_LIBRARIES 96 ${KNOWN_CONVENIENCE_LIBRARIES} ${TARGET} CACHE INTERNAL "" FORCE) 97 98 # Generate a cmake file which will save the name of the library. 99 CONFIGURE_FILE( 100 ${MYSQL_CMAKE_SCRIPT_DIR}/save_archive_location.cmake.in 101 ${CMAKE_BINARY_DIR}/archive_output_directory/lib_location_${TARGET}.cmake 102 @ONLY) 103 ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD 104 COMMAND ${CMAKE_COMMAND} 105 -DTARGET_NAME=${TARGET} 106 -DTARGET_LOC=$<TARGET_FILE:${TARGET}> 107 -DCFG_INTDIR=${CMAKE_CFG_INTDIR} 108 -P ${CMAKE_BINARY_DIR}/archive_output_directory/lib_location_${TARGET}.cmake 109 ) 110ENDMACRO() 111 112 113# An IMPORTED library can also be merged. 114MACRO(ADD_IMPORTED_LIBRARY TARGET LOC) 115 ADD_LIBRARY(${TARGET} STATIC IMPORTED) 116 SET_TARGET_PROPERTIES(${TARGET} PROPERTIES IMPORTED_LOCATION ${LOC}) 117 SET(KNOWN_CONVENIENCE_LIBRARIES 118 ${KNOWN_CONVENIENCE_LIBRARIES} ${TARGET} CACHE INTERNAL "" FORCE) 119 CONFIGURE_FILE( 120 ${MYSQL_CMAKE_SCRIPT_DIR}/save_archive_location.cmake.in 121 ${CMAKE_BINARY_DIR}/archive_output_directory/lib_location_${TARGET}.cmake 122 @ONLY) 123 ADD_CUSTOM_TARGET(${TARGET}_location 124 COMMAND ${CMAKE_COMMAND} 125 -DTARGET_NAME=${TARGET} 126 -DTARGET_LOC=$<TARGET_FILE:${TARGET}> 127 -DCFG_INTDIR=${CMAKE_CFG_INTDIR} 128 -P ${CMAKE_BINARY_DIR}/archive_output_directory/lib_location_${TARGET}.cmake 129 ) 130ENDMACRO() 131 132# Write content to file, using CONFIGURE_FILE 133# The advantage compared to FILE(WRITE) is that timestamp 134# does not change if file already has the same content 135MACRO(CONFIGURE_FILE_CONTENT content file) 136 SET(CMAKE_CONFIGURABLE_FILE_CONTENT 137 "${content}\n") 138 CONFIGURE_FILE( 139 ${MYSQL_CMAKE_SCRIPT_DIR}/configurable_file_content.in 140 ${file} 141 @ONLY) 142ENDMACRO() 143 144# Create libs from libs. 145# Merges static libraries, creates shared libraries out of convenience libraries. 146MACRO(MERGE_LIBRARIES_SHARED) 147 MYSQL_PARSE_ARGUMENTS(ARG 148 "EXPORTS;OUTPUT_NAME;COMPONENT" 149 "SKIP_INSTALL" 150 ${ARGN} 151 ) 152 LIST(GET ARG_DEFAULT_ARGS 0 TARGET) 153 SET(LIBS ${ARG_DEFAULT_ARGS}) 154 LIST(REMOVE_AT LIBS 0) 155 156 SET(LIBTYPE SHARED) 157 # check for non-PIC libraries 158 IF(NOT _SKIP_PIC) 159 FOREACH(LIB ${LIBS}) 160 GET_TARGET_PROPERTY(${LIB} TYPE LIBTYPE) 161 IF(LIBTYPE STREQUAL "STATIC_LIBRARY") 162 GET_TARGET_PROPERTY(LIB COMPILE_FLAGS LIB_COMPILE_FLAGS) 163 IF(NOT LIB_COMPILE_FLAGS MATCHES "<PIC_FLAG>") 164 MESSAGE(FATAL_ERROR 165 "Attempted to link non-PIC static library ${LIB} to shared library ${TARGET}\n" 166 "Please use ADD_CONVENIENCE_LIBRARY, instead of ADD_LIBRARY for ${LIB}" 167 ) 168 ENDIF() 169 ENDIF() 170 ENDFOREACH() 171 ENDIF() 172 CREATE_EXPORT_FILE(SRC ${TARGET} "${ARG_EXPORTS}") 173 IF(UNIX) 174 # Mark every export as explicitly needed, so that ld won't remove the .a files 175 # containing them. This has a similar effect as --Wl,--no-whole-archive, 176 # but is more focused. 177 FOREACH(SYMBOL ${ARG_EXPORTS}) 178 IF(APPLE) 179 SET(export_link_flags "${export_link_flags} -Wl,-u,_${SYMBOL}") 180 ELSE() 181 SET(export_link_flags "${export_link_flags} -Wl,-u,${SYMBOL}") 182 ENDIF() 183 ENDFOREACH() 184 ENDIF() 185 IF(NOT ARG_SKIP_INSTALL) 186 ADD_VERSION_INFO(${TARGET} SHARED SRC) 187 ENDIF() 188 ADD_LIBRARY(${TARGET} ${LIBTYPE} ${SRC}) 189 TARGET_LINK_LIBRARIES(${TARGET} ${LIBS}) 190 IF(ARG_OUTPUT_NAME) 191 SET_TARGET_PROPERTIES( 192 ${TARGET} PROPERTIES OUTPUT_NAME "${ARG_OUTPUT_NAME}") 193 ENDIF() 194 SET_TARGET_PROPERTIES( 195 ${TARGET} PROPERTIES LINK_FLAGS "${export_link_flags}") 196 197 IF(NOT ARG_SKIP_INSTALL) 198 IF(ARG_COMPONENT) 199 SET(COMP COMPONENT ${ARG_COMPONENT}) 200 ENDIF() 201 202 MYSQL_INSTALL_TARGETS(${TARGET} DESTINATION "${INSTALL_LIBDIR}" ${COMP}) 203 204 ENDIF() 205 SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_INTERFACE_LIBRARIES "") 206ENDMACRO() 207 208 209FUNCTION(GET_DEPENDEND_OS_LIBS target result) 210 SET(deps ${${target}_LIB_DEPENDS}) 211 IF(deps) 212 FOREACH(lib ${deps}) 213 # Filter out keywords for used for debug vs optimized builds 214 IF(NOT lib MATCHES "general" AND 215 NOT lib MATCHES "debug" AND 216 NOT lib MATCHES "optimized") 217 LIST(FIND KNOWN_CONVENIENCE_LIBRARIES ${lib} FOUNDIT) 218 IF(FOUNDIT LESS 0) 219 SET(ret ${ret} ${lib}) 220 ENDIF() 221 ENDIF() 222 ENDFOREACH() 223 ENDIF() 224 SET(${result} ${ret} PARENT_SCOPE) 225ENDFUNCTION() 226 227 228MACRO(MERGE_CONVENIENCE_LIBRARIES) 229 MYSQL_PARSE_ARGUMENTS(ARG 230 "OUTPUT_NAME;COMPONENT" 231 "SKIP_INSTALL" 232 ${ARGN} 233 ) 234 LIST(GET ARG_DEFAULT_ARGS 0 TARGET) 235 SET(LIBS ${ARG_DEFAULT_ARGS}) 236 LIST(REMOVE_AT LIBS 0) 237 238 SET(SOURCE_FILE 239 ${CMAKE_BINARY_DIR}/archive_output_directory/${TARGET}_depends.c) 240 ADD_LIBRARY(${TARGET} STATIC ${SOURCE_FILE}) 241 IF(ARG_OUTPUT_NAME) 242 SET_TARGET_PROPERTIES(${TARGET} PROPERTIES OUTPUT_NAME "${ARG_OUTPUT_NAME}") 243 ENDIF() 244 245 # Collect all static libraries in the same directory 246 SET_TARGET_PROPERTIES(${TARGET} PROPERTIES 247 ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/archive_output_directory) 248 249 # Go though the list of libraries. 250 # Known convenience libraries should have type "STATIC_LIBRARY" 251 # We assume that that unknown libraries (type "LIB_TYPE-NOTFOUND") 252 # are operating system libraries, to be linked with TARGET 253 SET(OSLIBS) 254 SET(MYLIBS) 255 FOREACH(LIB ${LIBS}) 256 GET_TARGET_PROPERTY(LIB_TYPE ${LIB} TYPE) 257 IF(LIB_TYPE STREQUAL "STATIC_LIBRARY") 258 LIST(FIND KNOWN_CONVENIENCE_LIBRARIES ${LIB} FOUNDIT) 259 IF(FOUNDIT LESS 0) 260 MESSAGE(STATUS "Known libs : ${KNOWN_CONVENIENCE_LIBRARIES}") 261 MESSAGE(FATAL_ERROR "Unknown static library ${LIB} FOUNDIT ${FOUNDIT}") 262 ELSE() 263 ADD_DEPENDENCIES(${TARGET} ${LIB}) 264 GET_TARGET_PROPERTY(loc ${LIB} IMPORTED_LOCATION) 265 IF(loc) 266 ADD_DEPENDENCIES(${TARGET} ${LIB}_location) 267 ENDIF() 268 LIST(APPEND MYLIBS ${LIB}) 269 GET_DEPENDEND_OS_LIBS(${LIB} LIB_OSLIBS) 270 IF(LIB_OSLIBS) 271 # MESSAGE(STATUS "GET_DEPENDEND_OS_LIBS ${LIB} : ${LIB_OSLIBS}") 272 LIST(APPEND OSLIBS ${LIB_OSLIBS}) 273 ENDIF() 274 ENDIF() 275 ELSE() 276 # 3rd party library like libz.so. Make sure that everything 277 # that links to our library links to this one as well. 278 LIST(APPEND OSLIBS ${LIB}) 279 ENDIF() 280 # MESSAGE(STATUS "LIB ${LIB} LIB_TYPE ${LIB_TYPE}") 281 ENDFOREACH() 282 283 IF(OSLIBS) 284 LIST(REMOVE_DUPLICATES OSLIBS) 285 TARGET_LINK_LIBRARIES(${TARGET} ${OSLIBS}) 286 MESSAGE(STATUS "Library ${TARGET} depends on OSLIBS ${OSLIBS}") 287 ENDIF() 288 289 # Make the generated dummy source file depended on all static input 290 # libs. If input lib changes,the source file is touched 291 # which causes the desired effect (relink). 292 ADD_CUSTOM_COMMAND( 293 OUTPUT ${SOURCE_FILE} 294 COMMAND ${CMAKE_COMMAND} -E touch ${SOURCE_FILE} 295 DEPENDS ${MYLIBS} 296 ) 297 298 MESSAGE(STATUS "MERGE_CONVENIENCE_LIBRARIES TARGET ${TARGET}") 299 MESSAGE(STATUS "MERGE_CONVENIENCE_LIBRARIES LIBS ${LIBS}") 300 MESSAGE(STATUS "MERGE_CONVENIENCE_LIBRARIES MYLIBS ${MYLIBS}") 301 302 CONFIGURE_FILE( 303 ${MYSQL_CMAKE_SCRIPT_DIR}/merge_archives.cmake.in 304 ${CMAKE_BINARY_DIR}/archive_output_directory/lib_merge_${TARGET}.cmake 305 @ONLY) 306 ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD 307 COMMAND ${CMAKE_COMMAND} 308 -DTARGET_NAME=${TARGET} 309 -DTARGET_LOC=$<TARGET_FILE:${TARGET}> 310 -DCFG_INTDIR=${CMAKE_CFG_INTDIR} 311 -P ${CMAKE_BINARY_DIR}/archive_output_directory/lib_merge_${TARGET}.cmake 312 COMMENT "Merging library ${TARGET}" 313 ) 314 315 IF(NOT ARG_SKIP_INSTALL) 316 IF(ARG_COMPONENT) 317 SET(COMP COMPONENT ${ARG_COMPONENT}) 318 ENDIF() 319 MYSQL_INSTALL_TARGETS(${TARGET} DESTINATION "${INSTALL_LIBDIR}" ${COMP}) 320 ENDIF() 321ENDMACRO() 322