1
0
Fork 0
All of Yzena's common CMake tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
11 KiB

# Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# This file exports macros that emulate some functionality found in GNU libtool
# on Unix systems. One such feature is convenience libraries. In this context,
# convenience library is a static library that can be linked to shared library
# On systems that force position-independent code, linking into shared library
# normally requires compilation with a special flag (often -fPIC).
# Some systems, like Windows or OSX do not need special compilation (Windows
# never uses PIC and OSX always uses it).
#
# The intention behind convenience libraries is simplify the build and to reduce
# excessive recompiles.
# Except for convenience libraries, this file provides macros to merge static
# libraries (we need it for mysqlclient) and to create shared library out of
# convenience libraries(again, for mysqlclient)
# Following macros are exported
# - ADD_CONVENIENCE_LIBRARY(target source1...sourceN)
# This macro creates convenience library. The functionality is similar to
# ADD_LIBRARY(target STATIC source1...sourceN), the difference is that resulting
# library can always be linked to shared library
#
# - MERGE_LIBRARIES(target [STATIC|SHARED|MODULE] [linklib1 .... linklibN]
# [EXPORTS exported_func1 .... exported_func_N]
# [OUTPUT_NAME output_name]
# This macro merges several static libraries into a single one or creates a shared
# library from several convenience libraries
# Important global flags
#
# - DISABLE_SHARED: If set, it is assumed that shared libraries are not produced
# during the build. ADD_CONVENIENCE_LIBRARY does not add anything to compile flags
GET_FILENAME_COMPONENT(MYSQL_CMAKE_SCRIPT_DIR ${CMAKE_CURRENT_LIST_FILE} PATH)
IF(WIN32 OR APPLE OR DISABLE_SHARED)
SET(_SKIP_PIC 1)
ENDIF()
INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/cmake_parse_arguments.cmake)
# CREATE_EXPORT_FILE (VAR target api_functions)
# Internal macro, used on Windows to export API functions as dllexport.
# Returns a list of extra files that should be linked into the library
# (in the variable pointed to by VAR).
MACRO(CREATE_EXPORT_FILE VAR TARGET API_FUNCTIONS)
SET(DUMMY ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_dummy.c)
CONFIGURE_FILE_CONTENT("" ${DUMMY})
IF(WIN32)
SET(EXPORTS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_exports.def)
SET(CONTENT "EXPORTS\n")
FOREACH(FUNC ${API_FUNCTIONS})
SET(CONTENT "${CONTENT} ${FUNC}\n")
ENDFOREACH()
CONFIGURE_FILE_CONTENT(${CONTENT} ${EXPORTS})
SET(${VAR} ${DUMMY} ${EXPORTS})
ELSE()
SET(${VAR} ${DUMMY})
ENDIF()
ENDMACRO()
# MYSQL_ADD_CONVENIENCE_LIBRARY(name source1...sourceN)
# Create static library that can be linked to shared library.
# On systems that force position-independent code, adds -fPIC or
# equivalent flag to compile flags.
MACRO(ADD_CONVENIENCE_LIBRARY)
SET(TARGET ${ARGV0})
SET(SOURCES ${ARGN})
LIST(REMOVE_AT SOURCES 0)
ADD_LIBRARY(${TARGET} STATIC ${SOURCES})
ENDMACRO()
# Write content to file, using CONFIGURE_FILE
# The advantage compared to FILE(WRITE) is that timestamp
# does not change if file already has the same content
MACRO(CONFIGURE_FILE_CONTENT content file)
SET(CMAKE_CONFIGURABLE_FILE_CONTENT
"${content}\n")
CONFIGURE_FILE(
${MYSQL_CMAKE_SCRIPT_DIR}/configurable_file_content.in
${file}
@ONLY)
ENDMACRO()
# Merge static libraries into a big static lib. The resulting library
# should not not have dependencies on other static libraries.
# We use it in MySQL to merge mysys,dbug,vio etc into mysqlclient
MACRO(MERGE_STATIC_LIBS TARGET OUTPUT_NAME LIBS_TO_MERGE)
# To produce a library we need at least one source file.
# It is created by ADD_CUSTOM_COMMAND below and will
# also help to track dependencies.
SET(SOURCE_FILE ${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_depends.c)
ADD_LIBRARY(${TARGET} STATIC ${SOURCE_FILE})
SET_TARGET_PROPERTIES(${TARGET} PROPERTIES OUTPUT_NAME ${OUTPUT_NAME})
SET(OSLIBS)
FOREACH(LIB ${LIBS_TO_MERGE})
GET_TARGET_PROPERTY(LIB_LOCATION ${LIB} LOCATION)
GET_TARGET_PROPERTY(LIB_TYPE ${LIB} TYPE)
IF(NOT LIB_LOCATION)
# 3rd party library like libz.so. Make sure that everything
# that links to our library links to this one as well.
LIST(APPEND OSLIBS ${LIB})
ELSE()
# This is a target in current project
# (can be a static or shared lib)
IF(LIB_TYPE STREQUAL "STATIC_LIBRARY")
SET(STATIC_LIBS ${STATIC_LIBS} ${LIB_LOCATION})
ADD_DEPENDENCIES(${TARGET} ${LIB})
# Extract dependend OS libraries
GET_DEPENDEND_OS_LIBS(${LIB} LIB_OSLIBS)
LIST(APPEND OSLIBS ${LIB_OSLIBS})
ELSE()
# This is a shared library our static lib depends on.
LIST(APPEND OSLIBS ${LIB})
ENDIF()
ENDIF()
ENDFOREACH()
IF(OSLIBS)
LIST(REMOVE_DUPLICATES OSLIBS)
TARGET_LINK_LIBRARIES(${TARGET} ${OSLIBS})
MESSAGE(STATUS "Library ${TARGET} depends on OSLIBS ${OSLIBS}")
ENDIF()
IF(STATIC_LIBS)
LIST(REMOVE_DUPLICATES STATIC_LIBS)
ENDIF()
# Make the generated dummy source file depended on all static input
# libs. If input lib changes,the source file is touched
# which causes the desired effect (relink).
ADD_CUSTOM_COMMAND(
OUTPUT ${SOURCE_FILE}
COMMAND ${CMAKE_COMMAND} -E touch ${SOURCE_FILE}
DEPENDS ${STATIC_LIBS})
IF(MSVC)
# To merge libs, just pass them to lib.exe command line.
SET(LINKER_EXTRA_FLAGS "")
FOREACH(LIB ${STATIC_LIBS})
SET(LINKER_EXTRA_FLAGS "${LINKER_EXTRA_FLAGS} ${LIB}")
ENDFOREACH()
SET_TARGET_PROPERTIES(${TARGET} PROPERTIES STATIC_LIBRARY_FLAGS
"${LINKER_EXTRA_FLAGS}")
ELSE()
GET_TARGET_PROPERTY(TARGET_LOCATION ${TARGET} LOCATION)
IF(APPLE)
# Use OSX's libtool to merge archives (ihandles universal
# binaries properly)
ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD
COMMAND rm ${TARGET_LOCATION}
COMMAND /usr/bin/libtool -static -o ${TARGET_LOCATION}
${STATIC_LIBS}
)
ELSE()
# Generic Unix or MinGW. In post-build step, call
# script, that extracts objects from archives with "ar x"
# and repacks them with "ar r"
SET(TARGET ${TARGET})
CONFIGURE_FILE(
${MYSQL_CMAKE_SCRIPT_DIR}/merge_archives_unix.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}.cmake
@ONLY
)
ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD
COMMAND rm ${TARGET_LOCATION}
COMMAND ${CMAKE_COMMAND} -P
${CMAKE_CURRENT_BINARY_DIR}/merge_archives_${TARGET}.cmake
)
ENDIF()
ENDIF()
ENDMACRO()
# Create libs from libs.
# Merges static libraries, creates shared libraries out of convenience libraries.
# MERGE_LIBRARIES(target [STATIC|SHARED|MODULE]
# [linklib1 .... linklibN]
# [EXPORTS exported_func1 .... exportedFuncN]
# [OUTPUT_NAME output_name]
#)
MACRO(MERGE_LIBRARIES)
MYSQL_PARSE_ARGUMENTS(ARG
"EXPORTS;OUTPUT_NAME;COMPONENT"
"STATIC;SHARED;MODULE;SKIP_INSTALL"
${ARGN}
)
LIST(GET ARG_DEFAULT_ARGS 0 TARGET)
SET(LIBS ${ARG_DEFAULT_ARGS})
LIST(REMOVE_AT LIBS 0)
IF(ARG_STATIC)
IF (NOT ARG_OUTPUT_NAME)
SET(ARG_OUTPUT_NAME ${TARGET})
ENDIF()
MERGE_STATIC_LIBS(${TARGET} ${ARG_OUTPUT_NAME} "${LIBS}")
ELSEIF(ARG_SHARED OR ARG_MODULE)
IF(ARG_SHARED)
SET(LIBTYPE SHARED)
ELSE()
SET(LIBTYPE MODULE)
ENDIF()
# check for non-PIC libraries
IF(NOT _SKIP_PIC)
FOREACH(LIB ${LIBS})
GET_TARGET_PROPERTY(${LIB} TYPE LIBTYPE)
IF(LIBTYPE STREQUAL "STATIC_LIBRARY")
GET_TARGET_PROPERTY(LIB COMPILE_FLAGS LIB_COMPILE_FLAGS)
IF(NOT LIB_COMPILE_FLAGS MATCHES "<PIC_FLAG>")
MESSAGE(FATAL_ERROR
"Attempted to link non-PIC static library ${LIB} to shared library ${TARGET}\n"
"Please use ADD_CONVENIENCE_LIBRARY, instead of ADD_LIBRARY for ${LIB}"
)
ENDIF()
ENDIF()
ENDFOREACH()
ENDIF()
CREATE_EXPORT_FILE(SRC ${TARGET} "${ARG_EXPORTS}")
IF(UNIX)
# Mark every export as explicitly needed, so that ld won't remove the .a files
# containing them. This has a similar effect as --Wl,--no-whole-archive,
# but is more focused.
FOREACH(SYMBOL ${ARG_EXPORTS})
IF(APPLE)
SET(export_link_flags "${export_link_flags} -Wl,-u,_${SYMBOL}")
ELSE()
SET(export_link_flags "${export_link_flags} -Wl,-u,${SYMBOL}")
ENDIF()
ENDFOREACH()
ENDIF()
IF(NOT ARG_SKIP_INSTALL)
ADD_VERSION_INFO(${TARGET} SHARED SRC)
ENDIF()
ADD_LIBRARY(${TARGET} ${LIBTYPE} ${SRC})
# Collect all dynamic libraries in the same directory
SET_TARGET_PROPERTIES(${TARGET} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/library_output_directory)
TARGET_LINK_LIBRARIES(${TARGET} ${LIBS})
IF(ARG_OUTPUT_NAME)
SET_TARGET_PROPERTIES(${TARGET} PROPERTIES OUTPUT_NAME "${ARG_OUTPUT_NAME}")
ENDIF()
SET_TARGET_PROPERTIES(${TARGET} PROPERTIES LINK_FLAGS "${export_link_flags}")
IF(APPLE AND HAVE_CRYPTO_DYLIB AND HAVE_OPENSSL_DYLIB)
ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD
COMMAND install_name_tool -change
"${CRYPTO_VERSION}" "@loader_path/${CRYPTO_VERSION}"
$<TARGET_SONAME_FILE:${TARGET}>
COMMAND install_name_tool -change
"${OPENSSL_VERSION}" "@loader_path/${OPENSSL_VERSION}"
$<TARGET_SONAME_FILE:${TARGET}>
COMMAND install_name_tool -id "$<TARGET_SONAME_FILE_NAME:${TARGET}>"
$<TARGET_SONAME_FILE:${TARGET}>
)
# All executables have dependencies: "@loader_path/../lib/xxx.dylib
# Create a symlink so that this works for Xcode also.
IF(NOT BUILD_IS_SINGLE_CONFIG)
ADD_CUSTOM_COMMAND(TARGET ${TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink
$<TARGET_SONAME_FILE_DIR:${TARGET}> lib
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/runtime_output_directory
)
ENDIF()
ENDIF()
ELSE()
MESSAGE(FATAL_ERROR "Unknown library type")
ENDIF()
IF(NOT ARG_SKIP_INSTALL)
IF(ARG_COMPONENT)
SET(COMP COMPONENT ${ARG_COMPONENT})
ENDIF()
IF(ARG_SHARED OR ARG_MODULE OR INSTALL_STATIC_LIBRARIES)
MYSQL_INSTALL_TARGETS(${TARGET} DESTINATION "${INSTALL_LIBDIR}" ${COMP})
ENDIF()
ENDIF()
ENDMACRO()
FUNCTION(GET_DEPENDEND_OS_LIBS target result)
SET(deps ${${target}_LIB_DEPENDS})
IF(deps)
FOREACH(lib ${deps})
# Filter out keywords for used for debug vs optimized builds
IF(NOT lib MATCHES "general" AND NOT lib MATCHES "debug" AND NOT lib MATCHES "optimized")
GET_TARGET_PROPERTY(lib_location ${lib} LOCATION)
IF(NOT lib_location)
SET(ret ${ret} ${lib})
ENDIF()
ENDIF()
ENDFOREACH()
ENDIF()
SET(${result} ${ret} PARENT_SCOPE)
ENDFUNCTION()