include(CheckCCompilerFlag) include(SwiftSupport) include(DTrace) add_library(dispatch allocator.c apply.c benchmark.c data.c init.c introspection.c io.c mach.c object.c once.c queue.c semaphore.c source.c time.c transform.c voucher.c shims.c protocol.defs provider.d allocator_internal.h data_internal.h inline_internal.h internal.h introspection_internal.h io_internal.h mach_internal.h object_internal.h queue_internal.h semaphore_internal.h shims.h source_internal.h trace.h voucher_internal.h event/event.c event/event_config.h event/event_epoll.c event/event_internal.h event/event_kevent.c event/event_windows.c firehose/firehose_internal.h shims/android_stubs.h shims/atomic.h shims/atomic_sfb.h shims/getprogname.h shims/hw_config.h shims/lock.c shims/lock.h shims/perfmon.h shims/time.h shims/tsd.h shims/yield.c shims/yield.h) set_target_properties(dispatch PROPERTIES POSITION_INDEPENDENT_CODE YES) if(WIN32) target_sources(dispatch PRIVATE shims/generic_sys_queue.h shims/generic_win_stubs.c shims/generic_win_stubs.h shims/getprogname.c) endif() if(DISPATCH_USE_INTERNAL_WORKQUEUE) target_sources(dispatch PRIVATE event/workqueue.c event/workqueue_internal.h) endif() target_sources(dispatch PRIVATE block.cpp) if(HAVE_OBJC) # TODO(compnerd) split DispatchStubs.cc into a separate component for the ObjC # registration and a separate component for the swift compiler's emission of a # call to the ObjC autorelease elision entry point. target_sources(dispatch PRIVATE data.m object.m swift/DispatchStubs.cc) endif() if(ENABLE_SWIFT) set(swift_optimization_flags) if(NOT CMAKE_BUILD_TYPE MATCHES Debug) set(swift_optimization_flags -O) endif() # NOTE(compnerd) Today regardless of whether or not ObjC interop is enabled, # swift will use an autoreleased return value convention for certain CF # functions (including some that are used/related to dispatch). This means # that the swift compiler in callers to such functions will call the function, # and then pass the result of the function to # objc_retainAutoreleasedReturnValue. In a context where we have ObjC interop # disabled, we do not have access to the objc runtime so an implementation of # objc_retainAutoreleasedReturnValue is not available. To work around this, we # provide a shim for objc_retainAutoreleasedReturnValue in DispatchStubs.cc # that just calls retain on the object. Once we fix the swift compiler to # switch to a different model for handling these arguments with objc-interop # disabled these shims can be eliminated. add_library(DispatchStubs STATIC swift/DispatchStubs.cc) target_include_directories(DispatchStubs PRIVATE ${PROJECT_SOURCE_DIR}) set_target_properties(DispatchStubs PROPERTIES POSITION_INDEPENDENT_CODE YES) if(USE_LLD_LINKER) if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) set(use_ld_flag -use-ld=lld.exe) else() set(use_ld_flag -use-ld=lld) endif() elseif(USE_GOLD_LINKER) if(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows) set(use_ld_flag -use-ld=gold.exe) else() set(use_ld_flag -use-ld=gold) endif() endif() add_swift_library(swiftDispatch CFLAGS -fblocks -fmodule-map-file=${PROJECT_SOURCE_DIR}/dispatch/module.modulemap DEPENDS module-maps DispatchStubs LINK_FLAGS ${use_ld_flag} -lDispatchStubs -L $ -lBlocksRuntime -L $ -ldispatch $<$,$>:-lmsvcrtd> $<$,$>>:-lmsvcrt> MODULE_NAME Dispatch MODULE_LINK_NAME swiftDispatch MODULE_PATH ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftmodule SOURCES swift/Block.swift swift/Data.swift swift/Dispatch.swift swift/IO.swift swift/Private.swift swift/Queue.swift swift/Source.swift swift/Time.swift swift/Wrapper.swift SWIFT_FLAGS -I ${PROJECT_SOURCE_DIR} ${swift_optimization_flags} $<$:-Xcc> $<$:-D_MT> # TODO(compnerd) handle /MT builds $<$:-Xcc> $<$:-D_DLL> TARGET ${CMAKE_SWIFT_COMPILER_TARGET}) endif() if(ENABLE_DTRACE) dtrace_usdt_probe(${CMAKE_CURRENT_SOURCE_DIR}/provider.d OUTPUT_SOURCES dispatch_dtrace_provider_headers) target_sources(dispatch PRIVATE ${dispatch_dtrace_provider_headers}) endif() target_include_directories(dispatch PRIVATE ${PROJECT_BINARY_DIR} ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${PROJECT_SOURCE_DIR}/private) target_include_directories(dispatch SYSTEM BEFORE PRIVATE "${BlocksRuntime_INCLUDE_DIR}") if(WIN32) target_compile_definitions(dispatch PRIVATE _CRT_NONSTDC_NO_WARNINGS) endif() if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC") target_compile_options(dispatch PRIVATE /EHs-c-) else() target_compile_options(dispatch PRIVATE -fno-exceptions) endif() if(DISPATCH_ENABLE_ASSERTS) target_compile_definitions(dispatch PRIVATE -DDISPATCH_DEBUG=1) endif() if(CMAKE_SYSTEM_NAME STREQUAL Windows) target_compile_definitions(dispatch PRIVATE -D_CRT_SECURE_NO_WARNINGS) elseif(CMAKE_SYSTEM_NAME STREQUAL Android) target_compile_options(dispatch PRIVATE -U_GNU_SOURCE) endif() if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC") target_compile_options(dispatch PRIVATE /W3) else() target_compile_options(dispatch PRIVATE -Wall) endif() # FIXME(compnerd) add check for -fblocks? if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC") target_compile_options(dispatch PRIVATE -Xclang -fblocks) else() check_c_compiler_flag("-momit-leaf-frame-pointer -Werror -Wall -O3" C_SUPPORTS_OMIT_LEAF_FRAME_POINTER) target_compile_options(dispatch PRIVATE -fblocks) if (C_SUPPORTS_OMIT_LEAF_FRAME_POINTER) target_compile_options(dispatch PRIVATE -momit-leaf-frame-pointer) endif() endif() if(LibRT_FOUND) target_link_libraries(dispatch PRIVATE RT::rt) endif() target_link_libraries(dispatch PRIVATE Threads::Threads BlocksRuntime::BlocksRuntime) if(CMAKE_SYSTEM_NAME STREQUAL Windows) target_link_libraries(dispatch PRIVATE ShLwApi WS2_32 WinMM synchronization) endif() if(CMAKE_SYSTEM_NAME STREQUAL Darwin) set_property(TARGET dispatch APPEND_STRING PROPERTY LINK_FLAGS "-Xlinker -compatibility_version -Xlinker 1" "-Xlinker -current_version -Xlinker ${VERSION}" "-Xlinker -dead_strip" "-Xlinker -alias_list -Xlinker ${PROJECT_SOURCE_DIR}/xcodeconfig/libdispatch.aliases") endif() dispatch_set_linker(dispatch) install(TARGETS dispatch ARCHIVE DESTINATION ${INSTALL_TARGET_DIR} LIBRARY DESTINATION ${INSTALL_TARGET_DIR} RUNTIME DESTINATION bin) if(ENABLE_SWIFT) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftmodule ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftdoc DESTINATION ${INSTALL_TARGET_DIR}/${swift_arch}) if(BUILD_SHARED_LIBS) set(library_kind SHARED) else() set(library_kind STATIC) endif() set(swiftDispatch_OUTPUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_${library_kind}_LIBRARY_PREFIX}swiftDispatch${CMAKE_${library_kind}_LIBRARY_SUFFIX}) if(CMAKE_SYSTEM_NAME STREQUAL Windows AND BUILD_SHARED_LIBS) install(FILES ${swiftDispatch_OUTPUT_FILE} DESTINATION bin) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_IMPORT_LIBRARY_PREFIX}swiftDispatch${CMAKE_IMPORT_LIBRARY_SUFFIX} DESTINATION ${INSTALL_TARGET_DIR}) else() install(FILES ${swiftDispatch_OUTPUT_FILE} DESTINATION ${INSTALL_TARGET_DIR}) endif() if(NOT BUILD_SHARED_LIBS) install(FILES $ DESTINATION ${INSTALL_TARGET_DIR}) endif() endif()