1# - Function for generation of export macros for libraries 2# This module provides the function GENERATE_EXPORT_HEADER() and the 3# accompanying ADD_COMPILER_EXPORT_FLAGS() function. 4# 5# The GENERATE_EXPORT_HEADER function can be used to generate a file suitable 6# for preprocessor inclusion which contains EXPORT macros to be used in 7# library classes. 8# 9# GENERATE_EXPORT_HEADER( LIBRARY_TARGET 10# [BASE_NAME <base_name>] 11# [EXPORT_MACRO_NAME <export_macro_name>] 12# [EXPORT_FILE_NAME <export_file_name>] 13# [DEPRECATED_MACRO_NAME <deprecated_macro_name>] 14# [NO_EXPORT_MACRO_NAME <no_export_macro_name>] 15# [STATIC_DEFINE <static_define>] 16# [NO_DEPRECATED_MACRO_NAME <no_deprecated_macro_name>] 17# [DEFINE_NO_DEPRECATED] 18# [PREFIX_NAME <prefix_name>] 19# ) 20# 21# ADD_COMPILER_EXPORT_FLAGS( [<output_variable>] ) 22# 23# By default GENERATE_EXPORT_HEADER() generates macro names in a file name 24# determined by the name of the library. The ADD_COMPILER_EXPORT_FLAGS function 25# adds -fvisibility=hidden to CMAKE_CXX_FLAGS if supported, and is a no-op on 26# Windows which does not need extra compiler flags for exporting support. You 27# may optionally pass a single argument to ADD_COMPILER_EXPORT_FLAGS that will 28# be populated with the required CXX_FLAGS required to enable visibility support 29# for the compiler/architecture in use. 30# 31# This means that in the simplest case, users of these functions will be 32# equivalent to: 33# 34# add_compiler_export_flags() 35# add_library(somelib someclass.cpp) 36# generate_export_header(somelib) 37# install(TARGETS somelib DESTINATION ${LIBRARY_INSTALL_DIR}) 38# install(FILES 39# someclass.h 40# ${PROJECT_BINARY_DIR}/somelib_export.h DESTINATION ${INCLUDE_INSTALL_DIR} 41# ) 42# 43# And in the ABI header files: 44# 45# #include "somelib_export.h" 46# class SOMELIB_EXPORT SomeClass { 47# ... 48# }; 49# 50# The CMake fragment will generate a file in the ${CMAKE_CURRENT_BUILD_DIR} 51# called somelib_export.h containing the macros SOMELIB_EXPORT, SOMELIB_NO_EXPORT, 52# SOMELIB_DEPRECATED, SOMELIB_DEPRECATED_EXPORT and SOMELIB_DEPRECATED_NO_EXPORT. 53# The resulting file should be installed with other headers in the library. 54# 55# The BASE_NAME argument can be used to override the file name and the names 56# used for the macros 57# 58# add_library(somelib someclass.cpp) 59# generate_export_header(somelib 60# BASE_NAME other_name 61# ) 62# 63# Generates a file called other_name_export.h containing the macros 64# OTHER_NAME_EXPORT, OTHER_NAME_NO_EXPORT and OTHER_NAME_DEPRECATED etc. 65# 66# The BASE_NAME may be overridden by specifiying other options in the function. 67# For example: 68# 69# add_library(somelib someclass.cpp) 70# generate_export_header(somelib 71# EXPORT_MACRO_NAME OTHER_NAME_EXPORT 72# ) 73# 74# creates the macro OTHER_NAME_EXPORT instead of SOMELIB_EXPORT, but other macros 75# and the generated file name is as default. 76# 77# add_library(somelib someclass.cpp) 78# generate_export_header(somelib 79# DEPRECATED_MACRO_NAME KDE_DEPRECATED 80# ) 81# 82# creates the macro KDE_DEPRECATED instead of SOMELIB_DEPRECATED. 83# 84# If LIBRARY_TARGET is a static library, macros are defined without values. 85# 86# If the same sources are used to create both a shared and a static library, the 87# uppercased symbol ${BASE_NAME}_STATIC_DEFINE should be used when building the 88# static library 89# 90# add_library(shared_variant SHARED ${lib_SRCS}) 91# add_library(static_variant ${lib_SRCS}) 92# generate_export_header(shared_variant BASE_NAME libshared_and_static) 93# set_target_properties(static_variant PROPERTIES 94# COMPILE_FLAGS -DLIBSHARED_AND_STATIC_STATIC_DEFINE) 95# 96# This will cause the export macros to expand to nothing when building the 97# static library. 98# 99# If DEFINE_NO_DEPRECATED is specified, then a macro ${BASE_NAME}_NO_DEPRECATED 100# will be defined 101# This macro can be used to remove deprecated code from preprocessor output. 102# 103# option(EXCLUDE_DEPRECATED "Exclude deprecated parts of the library" FALSE) 104# if (EXCLUDE_DEPRECATED) 105# set(NO_BUILD_DEPRECATED DEFINE_NO_DEPRECATED) 106# endif() 107# generate_export_header(somelib ${NO_BUILD_DEPRECATED}) 108# 109# And then in somelib: 110# 111# class SOMELIB_EXPORT SomeClass 112# { 113# public: 114# #ifndef SOMELIB_NO_DEPRECATED 115# SOMELIB_DEPRECATED void oldMethod(); 116# #endif 117# }; 118# 119# #ifndef SOMELIB_NO_DEPRECATED 120# void SomeClass::oldMethod() { } 121# #endif 122# 123# If PREFIX_NAME is specified, the argument will be used as a prefix to all 124# generated macros. 125# 126# For example: 127# 128# generate_export_header(somelib PREFIX_NAME VTK_) 129# 130# Generates the macros VTK_SOMELIB_EXPORT etc. 131 132#============================================================================= 133# Copyright 2011 Stephen Kelly <steveire@gmail.com> 134# 135# Distributed under the OSI-approved BSD License (the "License"); 136# see accompanying file Copyright.txt for details. 137# 138# This software is distributed WITHOUT ANY WARRANTY; without even the 139# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 140# See the License for more information. 141#============================================================================= 142# (To distribute this file outside of CMake, substitute the full 143# License text for the above reference.) 144 145include(_CMakeParseArguments) 146include(CheckCXXCompilerFlag) 147 148# TODO: Install this macro separately? 149macro(_check_cxx_compiler_attribute _ATTRIBUTE _RESULT) 150 check_cxx_source_compiles("${_ATTRIBUTE} int somefunc() { return 0; } 151 int main() { return somefunc();}" ${_RESULT} 152 ) 153endmacro() 154 155macro(_test_compiler_hidden_visibility) 156 157 if(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.2") 158 set(GCC_TOO_OLD TRUE) 159 message(WARNING "GCC version older than 4.2") 160 elseif(CMAKE_COMPILER_IS_GNUC AND CMAKE_C_COMPILER_VERSION VERSION_LESS "4.2") 161 set(GCC_TOO_OLD TRUE) 162 message(WARNING "GCC version older than 4.2") 163 elseif(CMAKE_CXX_COMPILER_ID MATCHES Intel AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0") 164 set(_INTEL_TOO_OLD TRUE) 165 message(WARNING "Intel compiler older than 12.0") 166 endif() 167 168 169 # Exclude XL here because it misinterprets -fvisibility=hidden even though 170 # the check_cxx_compiler_flag passes 171 # http://www.cdash.org/CDash/testDetails.php?test=109109951&build=1419259 172 if(NOT GCC_TOO_OLD 173 AND NOT _INTEL_TOO_OLD 174 AND NOT WIN32 175 AND NOT CYGWIN 176 AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES XL 177 AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES PGI 178 AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES Watcom) 179 check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY) 180 check_cxx_compiler_flag(-fvisibility-inlines-hidden 181 COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) 182 option(USE_COMPILER_HIDDEN_VISIBILITY 183 "Use HIDDEN visibility support if available." ON) 184 mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) 185 endif() 186endmacro() 187 188macro(_test_compiler_has_deprecated) 189 if("${CMAKE_CXX_COMPILER_ID}" MATCHES Borland 190 OR "${CMAKE_CXX_COMPILER_ID}" MATCHES HP 191 OR GCC_TOO_OLD 192 OR "${CMAKE_CXX_COMPILER_ID}" MATCHES PGI 193 OR "${CMAKE_CXX_COMPILER_ID}" MATCHES Watcom) 194 set(COMPILER_HAS_DEPRECATED "" CACHE INTERNAL 195 "Compiler support for a deprecated attribute") 196 else() 197 _check_cxx_compiler_attribute("__attribute__((__deprecated__))" 198 COMPILER_HAS_DEPRECATED_ATTR) 199 if(COMPILER_HAS_DEPRECATED_ATTR) 200 set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}" 201 CACHE INTERNAL "Compiler support for a deprecated attribute") 202 else() 203 _check_cxx_compiler_attribute("__declspec(deprecated)" 204 COMPILER_HAS_DEPRECATED) 205 endif() 206 endif() 207endmacro() 208 209get_filename_component(_GENERATE_EXPORT_HEADER_MODULE_DIR 210 "${CMAKE_CURRENT_LIST_FILE}" PATH) 211 212macro(_DO_SET_MACRO_VALUES TARGET_LIBRARY) 213 set(DEFINE_DEPRECATED) 214 set(DEFINE_EXPORT) 215 set(DEFINE_IMPORT) 216 set(DEFINE_NO_EXPORT) 217 218 if (COMPILER_HAS_DEPRECATED_ATTR) 219 set(DEFINE_DEPRECATED "__attribute__ ((__deprecated__))") 220 elseif(COMPILER_HAS_DEPRECATED) 221 set(DEFINE_DEPRECATED "__declspec(deprecated)") 222 endif() 223 224 get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) 225 226 if(NOT ${type} STREQUAL "STATIC_LIBRARY") 227 if(WIN32) 228 set(DEFINE_EXPORT "__declspec(dllexport)") 229 set(DEFINE_IMPORT "__declspec(dllimport)") 230 elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY) 231 set(DEFINE_EXPORT "__attribute__((visibility(\"default\")))") 232 set(DEFINE_IMPORT "__attribute__((visibility(\"default\")))") 233 set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") 234 endif() 235 endif() 236endmacro() 237 238macro(_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) 239 # Option overrides 240 set(options DEFINE_NO_DEPRECATED) 241 set(oneValueArgs PREFIX_NAME BASE_NAME EXPORT_MACRO_NAME EXPORT_FILE_NAME 242 DEPRECATED_MACRO_NAME NO_EXPORT_MACRO_NAME STATIC_DEFINE 243 NO_DEPRECATED_MACRO_NAME) 244 set(multiValueArgs) 245 246 cmake_parse_arguments(_GEH "${options}" "${oneValueArgs}" "${multiValueArgs}" 247 ${ARGN}) 248 249 set(BASE_NAME "${TARGET_LIBRARY}") 250 251 if(_GEH_BASE_NAME) 252 set(BASE_NAME ${_GEH_BASE_NAME}) 253 endif() 254 255 string(TOUPPER ${BASE_NAME} BASE_NAME_UPPER) 256 string(TOLOWER ${BASE_NAME} BASE_NAME_LOWER) 257 258 # Default options 259 set(EXPORT_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_EXPORT") 260 set(NO_EXPORT_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_NO_EXPORT") 261 set(EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME_LOWER}_export.h") 262 set(DEPRECATED_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_DEPRECATED") 263 set(STATIC_DEFINE "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_STATIC_DEFINE") 264 set(NO_DEPRECATED_MACRO_NAME 265 "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_NO_DEPRECATED") 266 267 if(_GEH_UNPARSED_ARGUMENTS) 268 message(FATAL_ERROR "Unknown keywords given to GENERATE_EXPORT_HEADER(): \"${_GEH_UNPARSED_ARGUMENTS}\"") 269 endif() 270 271 if(_GEH_EXPORT_MACRO_NAME) 272 set(EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_EXPORT_MACRO_NAME}) 273 endif() 274 if(_GEH_EXPORT_FILE_NAME) 275 if(IS_ABSOLUTE ${_GEH_EXPORT_FILE_NAME}) 276 set(EXPORT_FILE_NAME ${_GEH_EXPORT_FILE_NAME}) 277 else() 278 set(EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${_GEH_EXPORT_FILE_NAME}") 279 endif() 280 endif() 281 if(_GEH_DEPRECATED_MACRO_NAME) 282 set(DEPRECATED_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_DEPRECATED_MACRO_NAME}) 283 endif() 284 if(_GEH_NO_EXPORT_MACRO_NAME) 285 set(NO_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_NO_EXPORT_MACRO_NAME}) 286 endif() 287 if(_GEH_STATIC_DEFINE) 288 set(STATIC_DEFINE ${_GEH_PREFIX_NAME}${_GEH_STATIC_DEFINE}) 289 endif() 290 291 if(_GEH_DEFINE_NO_DEPRECATED) 292 set(DEFINE_NO_DEPRECATED TRUE) 293 endif() 294 295 if(_GEH_NO_DEPRECATED_MACRO_NAME) 296 set(NO_DEPRECATED_MACRO_NAME 297 ${_GEH_PREFIX_NAME}${_GEH_NO_DEPRECATED_MACRO_NAME}) 298 endif() 299 300 set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") 301 302 get_target_property(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY} DEFINE_SYMBOL) 303 304 if(NOT EXPORT_IMPORT_CONDITION) 305 set(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY}_EXPORTS) 306 endif() 307 308 configure_file("${_GENERATE_EXPORT_HEADER_MODULE_DIR}/exportheader.cmake.in" 309 "${EXPORT_FILE_NAME}" @ONLY) 310endmacro() 311 312function(GENERATE_EXPORT_HEADER TARGET_LIBRARY) 313 get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) 314 if(${type} STREQUAL "MODULE") 315 message(WARNING "This macro should not be used with libraries of type MODULE") 316 return() 317 endif() 318 if(NOT ${type} STREQUAL "STATIC_LIBRARY" AND NOT ${type} STREQUAL "SHARED_LIBRARY") 319 message(WARNING "This macro can only be used with libraries") 320 return() 321 endif() 322 _test_compiler_hidden_visibility() 323 _test_compiler_has_deprecated() 324 _do_set_macro_values(${TARGET_LIBRARY}) 325 _do_generate_export_header(${TARGET_LIBRARY} ${ARGN}) 326endfunction() 327 328function(add_compiler_export_flags) 329 330 _test_compiler_hidden_visibility() 331 _test_compiler_has_deprecated() 332 333 if(NOT (USE_COMPILER_HIDDEN_VISIBILITY AND COMPILER_HAS_HIDDEN_VISIBILITY)) 334 # Just return if there are no flags to add. 335 return() 336 endif() 337 338 set (EXTRA_FLAGS "-fvisibility=hidden") 339 340 if(COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) 341 set (EXTRA_FLAGS "${EXTRA_FLAGS} -fvisibility-inlines-hidden") 342 endif() 343 344 # Either return the extra flags needed in the supplied argument, or to the 345 # CMAKE_CXX_FLAGS if no argument is supplied. 346 if(ARGV0) 347 set(${ARGV0} "${EXTRA_FLAGS}" PARENT_SCOPE) 348 else() 349 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_FLAGS}" PARENT_SCOPE) 350 endif() 351endfunction() 352