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( [FATAL_WARNINGS] ) 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# Set variable <LIBRARY_TARGET>_EXPORT_CODE to specify custom content. 55# 56# The BASE_NAME argument can be used to override the file name and the names 57# used for the macros 58# 59# add_library(somelib someclass.cpp) 60# generate_export_header(somelib 61# BASE_NAME other_name 62# ) 63# 64# Generates a file called other_name_export.h containing the macros 65# OTHER_NAME_EXPORT, OTHER_NAME_NO_EXPORT and OTHER_NAME_DEPRECATED etc. 66# 67# The BASE_NAME may be overridden by specifiying other options in the function. 68# For example: 69# 70# add_library(somelib someclass.cpp) 71# generate_export_header(somelib 72# EXPORT_MACRO_NAME OTHER_NAME_EXPORT 73# ) 74# 75# creates the macro OTHER_NAME_EXPORT instead of SOMELIB_EXPORT, but other macros 76# and the generated file name is as default. 77# 78# add_library(somelib someclass.cpp) 79# generate_export_header(somelib 80# DEPRECATED_MACRO_NAME KDE_DEPRECATED 81# ) 82# 83# creates the macro KDE_DEPRECATED instead of SOMELIB_DEPRECATED. 84# 85# If LIBRARY_TARGET is a static library, macros are defined without values. 86# 87# If the same sources are used to create both a shared and a static library, the 88# uppercased symbol ${BASE_NAME}_STATIC_DEFINE should be used when building the 89# static library 90# 91# add_library(shared_variant SHARED ${lib_SRCS}) 92# add_library(static_variant ${lib_SRCS}) 93# generate_export_header(shared_variant BASE_NAME libshared_and_static) 94# set_target_properties(static_variant PROPERTIES 95# COMPILE_FLAGS -DLIBSHARED_AND_STATIC_STATIC_DEFINE) 96# 97# This will cause the export macros to expand to nothing when building the 98# static library. 99# 100# If DEFINE_NO_DEPRECATED is specified, then a macro ${BASE_NAME}_NO_DEPRECATED 101# will be defined 102# This macro can be used to remove deprecated code from preprocessor output. 103# 104# option(EXCLUDE_DEPRECATED "Exclude deprecated parts of the library" FALSE) 105# if (EXCLUDE_DEPRECATED) 106# set(NO_BUILD_DEPRECATED DEFINE_NO_DEPRECATED) 107# endif() 108# generate_export_header(somelib ${NO_BUILD_DEPRECATED}) 109# 110# And then in somelib: 111# 112# class SOMELIB_EXPORT SomeClass 113# { 114# public: 115# #ifndef SOMELIB_NO_DEPRECATED 116# SOMELIB_DEPRECATED void oldMethod(); 117# #endif 118# }; 119# 120# #ifndef SOMELIB_NO_DEPRECATED 121# void SomeClass::oldMethod() { } 122# #endif 123# 124# If PREFIX_NAME is specified, the argument will be used as a prefix to all 125# generated macros. 126# 127# For example: 128# 129# generate_export_header(somelib PREFIX_NAME VTK_) 130# 131# Generates the macros VTK_SOMELIB_EXPORT etc. 132 133#============================================================================= 134# Copyright 2011 Stephen Kelly <steveire@gmail.com> 135# 136# Distributed under the OSI-approved BSD License (the "License"); 137# see accompanying file Copyright.txt for details. 138# 139# This software is distributed WITHOUT ANY WARRANTY; without even the 140# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 141# See the License for more information. 142#============================================================================= 143# (To distribute this file outside of CMake, substitute the full 144# License text for the above reference.) 145 146include(CMakeParseArguments) 147include(CheckCXXCompilerFlag) 148 149# TODO: Install this macro separately? 150macro(_check_cxx_compiler_attribute _ATTRIBUTE _RESULT) 151 check_cxx_source_compiles("${_ATTRIBUTE} int somefunc() { return 0; } 152 int main() { return somefunc();}" ${_RESULT} 153 # Some compilers do not fail with a bad flag 154 FAIL_REGEX "unrecognized .*option" # GNU 155 FAIL_REGEX "ignoring unknown option" # MSVC 156 FAIL_REGEX "warning D9002" # MSVC, any lang 157 FAIL_REGEX "[Uu]nknown option" # HP 158 FAIL_REGEX "[Ww]arning: [Oo]ption" # SunPro 159 FAIL_REGEX "command option .* is not recognized" # XL 160 ) 161endmacro() 162 163macro(_test_compiler_hidden_visibility) 164 165 if(CMAKE_COMPILER_IS_GNUCXX) 166 execute_process(COMMAND ${CMAKE_C_COMPILER} ARGS --version 167 OUTPUT_VARIABLE _gcc_version_info 168 ERROR_VARIABLE _gcc_version_info) 169 string(REGEX MATCH "[0-9]\\.[0-9]" 170 _gcc_version "${_gcc_version_info}") 171 # gcc on mac just reports: "gcc (GCC) 3.3 20030304 ..." without the 172 # patch level, handle this here: 173 if(NOT _gcc_version) 174 string(REGEX REPLACE ".*\\(GCC\\).*([34]\\.[0-9]).*" "\\1.0" 175 _gcc_version "${_gcc_version_info}") 176 endif() 177 178 if(${_gcc_version} VERSION_LESS "4.2") 179 set(GCC_TOO_OLD TRUE) 180 endif() 181 endif() 182 183 if(CMAKE_CXX_COMPILER_ID MATCHES "Intel") 184 execute_process(COMMAND ${CMAKE_CXX_COMPILER} ARGS -V 185 OUTPUT_VARIABLE _intel_version_info 186 ERROR_VARIABLE _intel_version_info) 187 string(REGEX REPLACE ".*Version ([0-9]+(\\.[0-9]+)+).*" "\\1" 188 _intel_version "${_intel_version_info}") 189 190 if(_intel_version VERSION_LESS "12.0") 191 set(_INTEL_TOO_OLD TRUE) 192 endif() 193 endif() 194 195 196 # Exclude XL here because it misinterprets -fvisibility=hidden even though 197 # the check_cxx_compiler_flag passes 198 # http://www.cdash.org/CDash/testDetails.php?test=109109951&build=1419259 199 if(NOT GCC_TOO_OLD 200 AND NOT _INTEL_TOO_OLD 201 AND NOT WIN32 202 AND NOT CYGWIN 203 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "XL" 204 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "PGI" 205 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "Watcom") 206 check_cxx_compiler_flag(-fvisibility=hidden COMPILER_HAS_HIDDEN_VISIBILITY) 207 check_cxx_compiler_flag(-fvisibility-inlines-hidden 208 COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) 209 option(USE_COMPILER_HIDDEN_VISIBILITY 210 "Use HIDDEN visibility support if available." ON) 211 mark_as_advanced(USE_COMPILER_HIDDEN_VISIBILITY) 212 endif() 213endmacro() 214 215macro(_test_compiler_has_deprecated) 216 if(CMAKE_CXX_COMPILER_ID MATCHES "Borland" 217 OR CMAKE_CXX_COMPILER_ID MATCHES "HP" 218 OR GCC_TOO_OLD 219 OR CMAKE_CXX_COMPILER_ID MATCHES "PGI" 220 OR CMAKE_CXX_COMPILER_ID MATCHES "Watcom") 221 set(COMPILER_HAS_DEPRECATED "" CACHE INTERNAL 222 "Compiler support for a deprecated attribute") 223 else() 224 _check_cxx_compiler_attribute("__attribute__((__deprecated__))" 225 COMPILER_HAS_DEPRECATED_ATTR) 226 if(COMPILER_HAS_DEPRECATED_ATTR) 227 set(COMPILER_HAS_DEPRECATED "${COMPILER_HAS_DEPRECATED_ATTR}" 228 CACHE INTERNAL "Compiler support for a deprecated attribute") 229 else() 230 _check_cxx_compiler_attribute("__declspec(deprecated)" 231 COMPILER_HAS_DEPRECATED) 232 endif() 233 endif() 234endmacro() 235 236get_filename_component(_GENERATE_EXPORT_HEADER_MODULE_DIR 237 "${CMAKE_CURRENT_LIST_FILE}" PATH) 238 239macro(_DO_SET_MACRO_VALUES TARGET_LIBRARY) 240 set(DEFINE_DEPRECATED) 241 set(DEFINE_EXPORT) 242 set(DEFINE_IMPORT) 243 set(DEFINE_NO_EXPORT) 244 245 if (COMPILER_HAS_DEPRECATED_ATTR) 246 set(DEFINE_DEPRECATED "__attribute__ ((__deprecated__))") 247 elseif(COMPILER_HAS_DEPRECATED) 248 set(DEFINE_DEPRECATED "__declspec(deprecated)") 249 endif() 250 251 get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) 252 253 if(NOT type STREQUAL "STATIC_LIBRARY") 254 if(WIN32) 255 set(DEFINE_EXPORT "__declspec(dllexport)") 256 set(DEFINE_IMPORT "__declspec(dllimport)") 257 elseif(COMPILER_HAS_HIDDEN_VISIBILITY AND USE_COMPILER_HIDDEN_VISIBILITY) 258 set(DEFINE_EXPORT "__attribute__((visibility(\"default\")))") 259 set(DEFINE_IMPORT "__attribute__((visibility(\"default\")))") 260 set(DEFINE_NO_EXPORT "__attribute__((visibility(\"hidden\")))") 261 endif() 262 endif() 263endmacro() 264 265macro(_DO_GENERATE_EXPORT_HEADER TARGET_LIBRARY) 266 # Option overrides 267 set(options DEFINE_NO_DEPRECATED) 268 set(oneValueArgs PREFIX_NAME BASE_NAME EXPORT_MACRO_NAME EXPORT_FILE_NAME 269 DEPRECATED_MACRO_NAME NO_EXPORT_MACRO_NAME STATIC_DEFINE 270 NO_DEPRECATED_MACRO_NAME) 271 set(multiValueArgs) 272 273 cmake_parse_arguments(_GEH "${options}" "${oneValueArgs}" "${multiValueArgs}" 274 ${ARGN}) 275 276 set(BASE_NAME "${TARGET_LIBRARY}") 277 278 if(_GEH_BASE_NAME) 279 set(BASE_NAME ${_GEH_BASE_NAME}) 280 endif() 281 282 string(TOUPPER ${BASE_NAME} BASE_NAME_UPPER) 283 string(TOLOWER ${BASE_NAME} BASE_NAME_LOWER) 284 285 # Default options 286 set(EXPORT_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_EXPORT") 287 set(NO_EXPORT_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_NO_EXPORT") 288 set(EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${BASE_NAME_LOWER}_export.h") 289 set(DEPRECATED_MACRO_NAME "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_DEPRECATED") 290 set(STATIC_DEFINE "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_STATIC_DEFINE") 291 set(NO_DEPRECATED_MACRO_NAME 292 "${_GEH_PREFIX_NAME}${BASE_NAME_UPPER}_NO_DEPRECATED") 293 294 if(_GEH_UNPARSED_ARGUMENTS) 295 message(FATAL_ERROR "Unknown keywords given to GENERATE_EXPORT_HEADER(): \"${_GEH_UNPARSED_ARGUMENTS}\"") 296 endif() 297 298 if(_GEH_EXPORT_MACRO_NAME) 299 set(EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_EXPORT_MACRO_NAME}) 300 endif() 301 if(_GEH_EXPORT_FILE_NAME) 302 if(IS_ABSOLUTE _GEH_EXPORT_FILE_NAME) 303 set(EXPORT_FILE_NAME ${_GEH_EXPORT_FILE_NAME}) 304 else() 305 set(EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/${_GEH_EXPORT_FILE_NAME}") 306 endif() 307 endif() 308 if(_GEH_DEPRECATED_MACRO_NAME) 309 set(DEPRECATED_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_DEPRECATED_MACRO_NAME}) 310 endif() 311 if(_GEH_NO_EXPORT_MACRO_NAME) 312 set(NO_EXPORT_MACRO_NAME ${_GEH_PREFIX_NAME}${_GEH_NO_EXPORT_MACRO_NAME}) 313 endif() 314 if(_GEH_STATIC_DEFINE) 315 set(STATIC_DEFINE ${_GEH_PREFIX_NAME}${_GEH_STATIC_DEFINE}) 316 endif() 317 if(DEFINED ${TARGET_LIBRARY}_EXPORT_CODE) 318 set(EXPORT_CODE "${${TARGET_LIBRARY}_EXPORT_CODE}") 319 else() 320 set(EXPORT_CODE "") 321 endif() 322 323 if(_GEH_DEFINE_NO_DEPRECATED) 324 set(DEFINE_NO_DEPRECATED TRUE) 325 endif() 326 327 if(_GEH_NO_DEPRECATED_MACRO_NAME) 328 set(NO_DEPRECATED_MACRO_NAME 329 ${_GEH_PREFIX_NAME}${_GEH_NO_DEPRECATED_MACRO_NAME}) 330 endif() 331 332 set(INCLUDE_GUARD_NAME "${EXPORT_MACRO_NAME}_H") 333 334 get_target_property(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY} DEFINE_SYMBOL) 335 336 if(NOT EXPORT_IMPORT_CONDITION) 337 set(EXPORT_IMPORT_CONDITION ${TARGET_LIBRARY}_EXPORTS) 338 endif() 339 340 configure_file("${_GENERATE_EXPORT_HEADER_MODULE_DIR}/exportheader.cmake.in" 341 "${EXPORT_FILE_NAME}" @ONLY) 342endmacro() 343 344function(GENERATE_EXPORT_HEADER TARGET_LIBRARY) 345 get_property(type TARGET ${TARGET_LIBRARY} PROPERTY TYPE) 346 if(type STREQUAL "MODULE") 347 message(WARNING "This macro should not be used with libraries of type MODULE") 348 return() 349 endif() 350 if(NOT type STREQUAL "STATIC_LIBRARY" AND NOT type STREQUAL "SHARED_LIBRARY" AND NOT type STREQUAL "OBJECT_LIBRARY") 351 message(WARNING "This macro can only be used with libraries") 352 return() 353 endif() 354 _test_compiler_hidden_visibility() 355 _test_compiler_has_deprecated() 356 _do_set_macro_values(${TARGET_LIBRARY}) 357 _do_generate_export_header(${TARGET_LIBRARY} ${ARGN}) 358endfunction() 359 360function(add_compiler_export_flags) 361 362 _test_compiler_hidden_visibility() 363 _test_compiler_has_deprecated() 364 365 if(NOT (USE_COMPILER_HIDDEN_VISIBILITY AND COMPILER_HAS_HIDDEN_VISIBILITY)) 366 # Just return if there are no flags to add. 367 return() 368 endif() 369 370 set (EXTRA_FLAGS "-fvisibility=hidden") 371 372 if(COMPILER_HAS_HIDDEN_INLINE_VISIBILITY) 373 set (EXTRA_FLAGS "${EXTRA_FLAGS} -fvisibility-inlines-hidden") 374 endif() 375 376 # Either return the extra flags needed in the supplied argument, or to the 377 # CMAKE_CXX_FLAGS if no argument is supplied. 378 if(ARGV0) 379 set(${ARGV0} "${EXTRA_FLAGS}" PARENT_SCOPE) 380 else() 381 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_FLAGS}" PARENT_SCOPE) 382 endif() 383endfunction() 384