1################################################################################ 2# Python modules 3# MLIR's Python modules are both directly used by the core project and are 4# available for use and embedding into external projects (in their own 5# namespace and with their own deps). In order to facilitate this, python 6# artifacts are split between declarations, which make a subset of 7# things available to be built and "add", which in line with the normal LLVM 8# nomenclature, adds libraries. 9################################################################################ 10 11# Function: declare_mlir_python_sources 12# Declares pure python sources as part of a named grouping that can be built 13# later. 14# Arguments: 15# ROOT_DIR: Directory where the python namespace begins (defaults to 16# CMAKE_CURRENT_SOURCE_DIR). For non-relocatable sources, this will 17# typically just be the root of the python source tree (current directory). 18# For relocatable sources, this will point deeper into the directory that 19# can be relocated. For generated sources, can be relative to 20# CMAKE_CURRENT_BINARY_DIR. Generated and non generated sources cannot be 21# mixed. 22# ADD_TO_PARENT: Adds this source grouping to a previously declared source 23# grouping. Source groupings form a DAG. 24# SOURCES: List of specific source files relative to ROOT_DIR to include. 25# SOURCES_GLOB: List of glob patterns relative to ROOT_DIR to include. 26# DEST_PREFIX: Destination prefix to prepend to files in the python 27# package directory namespace. 28function(declare_mlir_python_sources name) 29 cmake_parse_arguments(ARG 30 "" 31 "ROOT_DIR;ADD_TO_PARENT;DEST_PREFIX" 32 "SOURCES;SOURCES_GLOB" 33 ${ARGN}) 34 35 if(NOT ARG_ROOT_DIR) 36 set(ARG_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 37 endif() 38 set(_install_destination "src/python/${name}") 39 40 # Process the glob. 41 set(_glob_sources) 42 if(ARG_SOURCES_GLOB) 43 set(_glob_spec ${ARG_SOURCES_GLOB}) 44 list(TRANSFORM _glob_spec PREPEND "${ARG_ROOT_DIR}/") 45 file(GLOB_RECURSE _glob_sources 46 RELATIVE "${ARG_ROOT_DIR}" 47 ${_glob_spec} 48 ) 49 list(APPEND ARG_SOURCES ${_glob_sources}) 50 endif() 51 52 # We create a custom target to carry properties and dependencies for 53 # generated sources. 54 add_library(${name} INTERFACE) 55 set(_file_depends "${ARG_SOURCES}") 56 list(TRANSFORM _file_depends PREPEND "${ARG_ROOT_DIR}/") 57 set_target_properties(${name} PROPERTIES 58 # Yes: Leading-lowercase property names are load bearing and the recommended 59 # way to do this: https://gitlab.kitware.com/cmake/cmake/-/issues/19261 60 # Note that ROOT_DIR and FILE_DEPENDS are not exported because they are 61 # only relevant to in-tree uses. 62 EXPORT_PROPERTIES "mlir_python_SOURCES_TYPE;mlir_python_DEST_PREFIX;mlir_python_DEST_PREFIX;mlir_python_SOURCES;mlir_python_DEPENDS" 63 mlir_python_SOURCES_TYPE pure 64 mlir_python_ROOT_DIR "${ARG_ROOT_DIR}" 65 mlir_python_DEST_PREFIX "${ARG_DEST_PREFIX}" 66 mlir_python_SOURCES "${ARG_SOURCES}" 67 mlir_python_FILE_DEPENDS "${_file_depends}" 68 mlir_python_DEPENDS "" 69 ) 70 # Note that an "include" directory has no meaning to such faux targets, 71 # but it is a CMake supported way to specify a directory search list in a 72 # way that works both in-tree and out. It has some super powers which are 73 # not possible to emulate with custom properties (because of the prohibition 74 # on using generator expressions in exported custom properties and the 75 # special dispensation for $<INSTALL_PREFIX>). 76 target_include_directories(${name} INTERFACE 77 "$<BUILD_INTERFACE:${ARG_ROOT_DIR}>" 78 "$<INSTALL_INTERFACE:${_install_destination}>" 79 ) 80 81 # Add to parent. 82 if(ARG_ADD_TO_PARENT) 83 set_property(TARGET ${ARG_ADD_TO_PARENT} APPEND PROPERTY mlir_python_DEPENDS ${name}) 84 endif() 85 86 # Install. 87 if(NOT LLVM_INSTALL_TOOLCHAIN_ONLY) 88 _mlir_python_install_sources( 89 ${name} "${ARG_ROOT_DIR}" "${_install_destination}" 90 ${ARG_SOURCES} 91 ) 92 endif() 93endfunction() 94 95# Function: declare_mlir_python_extension 96# Declares a buildable python extension from C++ source files. The built 97# module is considered a python source file and included as everything else. 98# Arguments: 99# ROOT_DIR: Root directory where sources are interpreted relative to. 100# Defaults to CMAKE_CURRENT_SOURCE_DIR. 101# MODULE_NAME: Local import name of the module (i.e. "_mlir"). 102# ADD_TO_PARENT: Same as for declare_mlir_python_sources. 103# SOURCES: C++ sources making up the module. 104# PRIVATE_LINK_LIBS: List of libraries to link in privately to the module 105# regardless of how it is included in the project (generally should be 106# static libraries that can be included with hidden visibility). 107# EMBED_CAPI_LINK_LIBS: Dependent CAPI libraries that this extension depends 108# on. These will be collected for all extensions and put into an 109# aggregate dylib that is linked against. 110function(declare_mlir_python_extension name) 111 cmake_parse_arguments(ARG 112 "" 113 "ROOT_DIR;MODULE_NAME;ADD_TO_PARENT" 114 "SOURCES;PRIVATE_LINK_LIBS;EMBED_CAPI_LINK_LIBS" 115 ${ARGN}) 116 117 if(NOT ARG_ROOT_DIR) 118 set(ARG_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}") 119 endif() 120 set(_install_destination "src/python/${name}") 121 122 add_library(${name} INTERFACE) 123 set_target_properties(${name} PROPERTIES 124 # Yes: Leading-lowercase property names are load bearing and the recommended 125 # way to do this: https://gitlab.kitware.com/cmake/cmake/-/issues/19261 126 # Note that ROOT_DIR and FILE_DEPENDS are not exported because they are 127 # only relevant to in-tree uses. 128 EXPORT_PROPERTIES "mlir_python_SOURCES_TYPE;mlir_python_EXTENSION_MODULE_NAME;mlir_python_CPP_SOURCES;mlir_python_PRIVATE_LINK_LIBS;mlir_python_EMBED_CAPI_LINK_LIBS;mlir_python_DEPENDS" 129 mlir_python_SOURCES_TYPE extension 130 mlir_python_ROOT_DIR "${ARG_ROOT_DIR}" 131 mlir_python_EXTENSION_MODULE_NAME "${ARG_MODULE_NAME}" 132 mlir_python_CPP_SOURCES "${ARG_SOURCES}" 133 mlir_python_PRIVATE_LINK_LIBS "${ARG_PRIVATE_LINK_LIBS}" 134 mlir_python_EMBED_CAPI_LINK_LIBS "${ARG_EMBED_CAPI_LINK_LIBS}" 135 mlir_python_FILE_DEPENDS "" 136 mlir_python_DEPENDS "" 137 ) 138 # Note that an "include" directory has no meaning to such faux targets, 139 # but it is a CMake supported way to specify an install-prefix relative 140 # directory. It has some super powers which are not possible to emulate 141 # with custom properties (because of the prohibition on using generator 142 # expressions in exported custom properties and the special dispensation 143 # for $<INSTALL_PREFIX> and $<INSTALL_INTERFACE>). On imported targets, 144 # this is used as a single value, not as a list, so it must only have one 145 # item in it. 146 target_include_directories(${name} INTERFACE 147 "$<INSTALL_INTERFACE:${_install_destination}>" 148 ) 149 150 # Add to parent. 151 if(ARG_ADD_TO_PARENT) 152 set_property(TARGET ${ARG_ADD_TO_PARENT} APPEND PROPERTY mlir_python_DEPENDS ${name}) 153 endif() 154 155 # Install. 156 if(NOT LLVM_INSTALL_TOOLCHAIN_ONLY) 157 _mlir_python_install_sources( 158 ${name} "${ARG_ROOT_DIR}" "src/python/${name}" 159 ${ARG_SOURCES} 160 ) 161 endif() 162endfunction() 163 164function(_mlir_python_install_sources name source_root_dir destination) 165 foreach(source_relative_path ${ARGN}) 166 # Transform "a/b/c.py" -> "${install_prefix}/a/b" for installation. 167 get_filename_component( 168 dest_relative_path "${source_relative_path}" DIRECTORY 169 BASE_DIR "${source_root_dir}" 170 ) 171 install( 172 FILES "${source_root_dir}/${source_relative_path}" 173 DESTINATION "${destination}/${dest_relative_path}" 174 COMPONENT "${name}" 175 ) 176 endforeach() 177 get_target_export_arg(${name} MLIR export_to_mlirtargets UMBRELLA mlir-libraries) 178 install(TARGETS ${name} 179 COMPONENT ${name} 180 ${export_to_mlirtargets} 181 ) 182endfunction() 183 184# Function: add_mlir_python_modules 185# Adds python modules to a project, building them from a list of declared 186# source groupings (see declare_mlir_python_sources and 187# declare_mlir_python_extension). One of these must be called for each 188# packaging root in use. 189# Arguments: 190# ROOT_PREFIX: The directory in the build tree to emit sources. This will 191# typically be something like ${MY_BINARY_DIR}/python_packages/foobar 192# for non-relocatable modules or a deeper directory tree for relocatable. 193# INSTALL_PREFIX: Prefix into the install tree for installing the package. 194# Typically mirrors the path above but without an absolute path. 195# DECLARED_SOURCES: List of declared source groups to include. The entire 196# DAG of source modules is included. 197# COMMON_CAPI_LINK_LIBS: List of dylibs (typically one) to make every 198# extension depend on (see mlir_python_add_common_capi_library). 199function(add_mlir_python_modules name) 200 cmake_parse_arguments(ARG 201 "" 202 "ROOT_PREFIX;INSTALL_PREFIX;COMMON_CAPI_LINK_LIBS" 203 "DECLARED_SOURCES" 204 ${ARGN}) 205 # Helper to process an individual target. 206 function(_process_target modules_target sources_target) 207 get_target_property(_source_type ${sources_target} mlir_python_SOURCES_TYPE) 208 209 # The root directory differs based on whether it is IMPORTED (installed 210 # dep). 211 get_target_property(_is_imported ${sources_target} IMPORTED) 212 if(NOT _is_imported) 213 # In-tree. 214 get_target_property(_python_root_dir ${sources_target} mlir_python_ROOT_DIR) 215 else() 216 # Imported. 217 # Note: We only populate a single directory in 218 # INTERFACE_INCLUDE_DIRECTORIES, so we can get away with just using it 219 # as a single value. 220 get_target_property(_python_root_dir ${sources_target} INTERFACE_INCLUDE_DIRECTORIES) 221 endif() 222 223 if(_source_type STREQUAL "pure") 224 # Pure python sources to link into the tree. 225 get_target_property(_python_sources ${sources_target} mlir_python_SOURCES) 226 get_target_property(_specified_dest_prefix ${sources_target} mlir_python_DEST_PREFIX) 227 foreach(_source_relative_path ${_python_sources}) 228 set(_dest_relative_path "${_source_relative_path}") 229 if(_specified_dest_prefix) 230 set(_dest_relative_path "${_specified_dest_prefix}/${_dest_relative_path}") 231 endif() 232 set(_src_path "${_python_root_dir}/${_source_relative_path}") 233 set(_dest_path "${ARG_ROOT_PREFIX}/${_dest_relative_path}") 234 235 get_filename_component(_dest_dir "${_dest_path}" DIRECTORY) 236 get_filename_component(_install_path "${ARG_INSTALL_PREFIX}/${_dest_relative_path}" DIRECTORY) 237 238 file(MAKE_DIRECTORY "${_dest_dir}") 239 add_custom_command( 240 TARGET ${modules_target} PRE_BUILD 241 COMMENT "Copying python source ${_src_path} -> ${_dest_path}" 242 DEPENDS "${_src_path}" 243 BYPRODUCTS "${_dest_path}" 244 COMMAND "${CMAKE_COMMAND}" -E create_symlink 245 "${_src_path}" "${_dest_path}" 246 ) 247 install( 248 FILES "${_src_path}" 249 DESTINATION "${_install_path}" 250 COMPONENT ${modules_target} 251 ) 252 endforeach() 253 elseif(_source_type STREQUAL "extension") 254 # Native CPP extension. 255 get_target_property(_module_name ${sources_target} mlir_python_EXTENSION_MODULE_NAME) 256 get_target_property(_cpp_sources ${sources_target} mlir_python_CPP_SOURCES) 257 get_target_property(_private_link_libs ${sources_target} mlir_python_PRIVATE_LINK_LIBS) 258 # Transform relative source to based on root dir. 259 list(TRANSFORM _cpp_sources PREPEND "${_python_root_dir}/") 260 set(_extension_target "${name}.extension.${_module_name}.dso") 261 add_mlir_python_extension(${_extension_target} "${_module_name}" 262 INSTALL_COMPONENT ${modules_target} 263 INSTALL_DIR "${ARG_INSTALL_PREFIX}/_mlir_libs" 264 OUTPUT_DIRECTORY "${ARG_ROOT_PREFIX}/_mlir_libs" 265 SOURCES ${_cpp_sources} 266 LINK_LIBS PRIVATE 267 ${_private_link_libs} 268 ${ARG_COMMON_CAPI_LINK_LIBS} 269 ) 270 add_dependencies(${name} ${_extension_target}) 271 mlir_python_setup_extension_rpath(${_extension_target}) 272 else() 273 message(SEND_ERROR "Unrecognized source type '${_source_type}' for python source target ${sources_target}") 274 return() 275 endif() 276 endfunction() 277 278 _flatten_mlir_python_targets(_flat_targets ${ARG_DECLARED_SOURCES}) 279 # Collect dependencies. 280 set(_depends) 281 foreach(sources_target ${_flat_targets}) 282 get_target_property(_local_depends ${sources_target} mlir_python_FILE_DEPENDS) 283 if(_local_depends) 284 list(APPEND _depends ${_local_depends}) 285 endif() 286 endforeach() 287 288 # Build the modules target. 289 add_custom_target(${name} ALL DEPENDS ${_depends}) 290 foreach(sources_target ${_flat_targets}) 291 _process_target(${name} ${sources_target}) 292 endforeach() 293 294 # Create an install target. 295 if (NOT LLVM_ENABLE_IDE) 296 add_llvm_install_targets( 297 install-${name} 298 DEPENDS ${name} 299 COMPONENT ${name}) 300 endif() 301endfunction() 302 303# Function: declare_mlir_dialect_python_bindings 304# Helper to generate source groups for dialects, including both static source 305# files and a TD_FILE to generate wrappers. 306# 307# This will generate a source group named ${ADD_TO_PARENT}.${DIALECT_NAME}. 308# 309# Arguments: 310# ROOT_DIR: Same as for declare_mlir_python_sources(). 311# ADD_TO_PARENT: Same as for declare_mlir_python_sources(). Unique names 312# for the subordinate source groups are derived from this. 313# TD_FILE: Tablegen file to generate source for (relative to ROOT_DIR). 314# DIALECT_NAME: Python name of the dialect. 315# SOURCES: Same as declare_mlir_python_sources(). 316# SOURCES_GLOB: Same as declare_mlir_python_sources(). 317# DEPENDS: Additional dependency targets. 318function(declare_mlir_dialect_python_bindings) 319 cmake_parse_arguments(ARG 320 "" 321 "ROOT_DIR;ADD_TO_PARENT;TD_FILE;DIALECT_NAME" 322 "SOURCES;SOURCES_GLOB;DEPENDS" 323 ${ARGN}) 324 # Sources. 325 set(_dialect_target "${ARG_ADD_TO_PARENT}.${ARG_DIALECT_NAME}") 326 declare_mlir_python_sources(${_dialect_target} 327 ROOT_DIR "${ARG_ROOT_DIR}" 328 ADD_TO_PARENT "${ARG_ADD_TO_PARENT}" 329 SOURCES "${ARG_SOURCES}" 330 SOURCES_GLOB "${ARG_SOURCES_GLOB}" 331 ) 332 333 # Tablegen 334 if(ARG_TD_FILE) 335 set(tblgen_target "${ARG_ADD_TO}.${ARG_DIALECT_NAME}.tablegen") 336 set(td_file "${ARG_ROOT_DIR}/${ARG_TD_FILE}") 337 get_filename_component(relative_td_directory "${ARG_TD_FILE}" DIRECTORY) 338 set(dialect_filename "${relative_td_directory}/_${ARG_DIALECT_NAME}_ops_gen.py") 339 set(LLVM_TARGET_DEFINITIONS ${td_file}) 340 mlir_tablegen("${dialect_filename}" -gen-python-op-bindings 341 -bind-dialect=${ARG_DIALECT_NAME}) 342 add_public_tablegen_target(${tblgen_target}) 343 if(ARG_DEPENDS) 344 add_dependencies(${tblgen_target} ${ARG_DEPENDS}) 345 endif() 346 347 # Generated. 348 declare_mlir_python_sources("${ARG_ADD_TO_PARENT}.${ARG_DIALECT_NAME}.ops_gen" 349 ROOT_DIR "${CMAKE_CURRENT_BINARY_DIR}" 350 ADD_TO_PARENT "${_dialect_target}" 351 SOURCES "${dialect_filename}" 352 ) 353 endif() 354endfunction() 355 356# Function: mlir_python_setup_extension_rpath 357# Sets RPATH properties on a target, assuming that it is being output to 358# an _mlir_libs directory with all other libraries. For static linkage, 359# the RPATH will just be the origin. If linking dynamically, then the LLVM 360# library directory will be added. 361# Arguments: 362# RELATIVE_INSTALL_ROOT: If building dynamically, an RPATH entry will be 363# added to the install tree lib/ directory by first traversing this 364# path relative to the installation location. Typically a number of ".." 365# entries, one for each level of the install path. 366function(mlir_python_setup_extension_rpath target) 367 cmake_parse_arguments(ARG 368 "" 369 "RELATIVE_INSTALL_ROOT" 370 "" 371 ${ARGN}) 372 373 # RPATH handling. 374 # For the build tree, include the LLVM lib directory and the current 375 # directory for RPATH searching. For install, just the current directory 376 # (assumes that needed dependencies have been installed). 377 if(NOT APPLE AND NOT UNIX) 378 return() 379 endif() 380 381 set(_origin_prefix "\$ORIGIN") 382 if(APPLE) 383 set(_origin_prefix "@loader_path") 384 endif() 385 set_target_properties(${target} PROPERTIES 386 BUILD_WITH_INSTALL_RPATH OFF 387 BUILD_RPATH "${_origin_prefix}" 388 INSTALL_RPATH "${_origin_prefix}" 389 ) 390 391 # For static builds, that is all that is needed: all dependencies will be in 392 # the one directory. For shared builds, then we also need to add the global 393 # lib directory. This will be absolute for the build tree and relative for 394 # install. 395 # When we have access to CMake >= 3.20, there is a helper to calculate this. 396 if(BUILD_SHARED_LIBS AND ARG_RELATIVE_INSTALL_ROOT) 397 get_filename_component(_real_lib_dir "${LLVM_LIBRARY_OUTPUT_INTDIR}" REALPATH) 398 set_property(TARGET ${target} APPEND PROPERTY 399 BUILD_RPATH "${_real_lib_dir}") 400 set_property(TARGET ${target} APPEND PROPERTY 401 INSTALL_RPATH "${_origin_prefix}/${ARG_RELATIVE_INSTALL_ROOT}/lib${LLVM_LIBDIR_SUFFIX}") 402 endif() 403endfunction() 404 405# Function: add_mlir_python_common_capi_library 406# Adds a shared library which embeds dependent CAPI libraries needed to link 407# all extensions. 408# Arguments: 409# INSTALL_COMPONENT: Name of the install component. Typically same as the 410# target name passed to add_mlir_python_modules(). 411# INSTALL_DESTINATION: Prefix into the install tree in which to install the 412# library. 413# OUTPUT_DIRECTORY: Full path in the build tree in which to create the 414# library. Typically, this will be the common _mlir_libs directory where 415# all extensions are emitted. 416# RELATIVE_INSTALL_ROOT: See mlir_python_setup_extension_rpath(). 417# DECLARED_SOURCES: Source groups from which to discover dependent 418# EMBED_CAPI_LINK_LIBS. 419# EMBED_LIBS: Additional libraries to embed (must be built with OBJECTS and 420# have an "obj.${name}" object library associated). 421function(add_mlir_python_common_capi_library name) 422 cmake_parse_arguments(ARG 423 "" 424 "INSTALL_COMPONENT;INSTALL_DESTINATION;OUTPUT_DIRECTORY;RELATIVE_INSTALL_ROOT" 425 "DECLARED_SOURCES;EMBED_LIBS" 426 ${ARGN}) 427 # Collect all explicit and transitive embed libs. 428 set(_embed_libs ${ARG_EMBED_LIBS}) 429 _flatten_mlir_python_targets(_all_source_targets ${ARG_DECLARED_SOURCES}) 430 foreach(t ${_all_source_targets}) 431 get_target_property(_local_embed_libs ${t} mlir_python_EMBED_CAPI_LINK_LIBS) 432 if(_local_embed_libs) 433 list(APPEND _embed_libs ${_local_embed_libs}) 434 endif() 435 endforeach() 436 list(REMOVE_DUPLICATES _embed_libs) 437 438 # Generate the aggregate .so that everything depends on. 439 add_mlir_aggregate(${name} 440 SHARED 441 DISABLE_INSTALL 442 EMBED_LIBS ${_embed_libs} 443 ) 444 445 if(MSVC) 446 set_property(TARGET ${name} PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON) 447 endif() 448 set_target_properties(${name} PROPERTIES 449 LIBRARY_OUTPUT_DIRECTORY "${ARG_OUTPUT_DIRECTORY}" 450 BINARY_OUTPUT_DIRECTORY "${ARG_OUTPUT_DIRECTORY}" 451 # Needed for windows (and don't hurt others). 452 RUNTIME_OUTPUT_DIRECTORY "${ARG_OUTPUT_DIRECTORY}" 453 ARCHIVE_OUTPUT_DIRECTORY "${ARG_OUTPUT_DIRECTORY}" 454 ) 455 mlir_python_setup_extension_rpath(${name} 456 RELATIVE_INSTALL_ROOT "${ARG_RELATIVE_INSTALL_ROOT}" 457 ) 458 install(TARGETS ${name} 459 COMPONENT ${ARG_INSTALL_COMPONENT} 460 LIBRARY DESTINATION "${ARG_INSTALL_DESTINATION}" 461 RUNTIME DESTINATION "${ARG_INSTALL_DESTINATION}" 462 ) 463 464endfunction() 465 466function(_flatten_mlir_python_targets output_var) 467 set(_flattened) 468 foreach(t ${ARGN}) 469 get_target_property(_source_type ${t} mlir_python_SOURCES_TYPE) 470 get_target_property(_depends ${t} mlir_python_DEPENDS) 471 if(_source_type) 472 list(APPEND _flattened "${t}") 473 if(_depends) 474 _flatten_mlir_python_targets(_local_flattened ${_depends}) 475 list(APPEND _flattened ${_local_flattened}) 476 endif() 477 endif() 478 endforeach() 479 list(REMOVE_DUPLICATES _flattened) 480 set(${output_var} "${_flattened}" PARENT_SCOPE) 481endfunction() 482 483################################################################################ 484# Build python extension 485################################################################################ 486function(add_mlir_python_extension libname extname) 487 cmake_parse_arguments(ARG 488 "" 489 "INSTALL_COMPONENT;INSTALL_DIR;OUTPUT_DIRECTORY" 490 "SOURCES;LINK_LIBS" 491 ${ARGN}) 492 if (ARG_UNPARSED_ARGUMENTS) 493 message(FATAL_ERROR " Unhandled arguments to add_mlir_python_extension(${libname}, ... : ${ARG_UNPARSED_ARGUMENTS}") 494 endif() 495 if ("${ARG_SOURCES}" STREQUAL "") 496 message(FATAL_ERROR " Missing SOURCES argument to add_mlir_python_extension(${libname}, ...") 497 endif() 498 499 # The actual extension library produces a shared-object or DLL and has 500 # sources that must be compiled in accordance with pybind11 needs (RTTI and 501 # exceptions). 502 pybind11_add_module(${libname} 503 ${ARG_SOURCES} 504 ) 505 506 # The extension itself must be compiled with RTTI and exceptions enabled. 507 # Also, some warning classes triggered by pybind11 are disabled. 508 target_compile_options(${libname} PRIVATE 509 $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>: 510 # Enable RTTI and exceptions. 511 -frtti -fexceptions 512 > 513 $<$<CXX_COMPILER_ID:MSVC>: 514 # Enable RTTI and exceptions. 515 /EHsc /GR> 516 ) 517 518 # Configure the output to match python expectations. 519 set_target_properties( 520 ${libname} PROPERTIES 521 LIBRARY_OUTPUT_DIRECTORY ${ARG_OUTPUT_DIRECTORY} 522 OUTPUT_NAME "${extname}" 523 NO_SONAME ON 524 ) 525 526 if(WIN32) 527 # Need to also set the RUNTIME_OUTPUT_DIRECTORY on Windows in order to 528 # control where the .dll gets written. 529 set_target_properties( 530 ${libname} PROPERTIES 531 RUNTIME_OUTPUT_DIRECTORY ${ARG_OUTPUT_DIRECTORY} 532 ARCHIVE_OUTPUT_DIRECTORY ${ARG_OUTPUT_DIRECTORY} 533 ) 534 endif() 535 536 # Python extensions depends *only* on the public API and LLVMSupport unless 537 # if further dependencies are added explicitly. 538 target_link_libraries(${libname} 539 PRIVATE 540 ${ARG_LINK_LIBS} 541 ${PYEXT_LIBADD} 542 ) 543 544 target_link_options(${libname} 545 PRIVATE 546 # On Linux, disable re-export of any static linked libraries that 547 # came through. 548 $<$<PLATFORM_ID:Linux>:LINKER:--exclude-libs,ALL> 549 ) 550 551 ################################################################################ 552 # Install 553 ################################################################################ 554 if (ARG_INSTALL_DIR) 555 install(TARGETS ${libname} 556 COMPONENT ${ARG_INSTALL_COMPONENT} 557 LIBRARY DESTINATION ${ARG_INSTALL_DIR} 558 ARCHIVE DESTINATION ${ARG_INSTALL_DIR} 559 # NOTE: Even on DLL-platforms, extensions go in the lib directory tree. 560 RUNTIME DESTINATION ${ARG_INSTALL_DIR} 561 ) 562 endif() 563endfunction() 564