From 71942ed8469fe25547d0a0a322655a3c2e662593 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 11 Oct 2018 21:18:24 -0700 Subject: [PATCH 1/4] cmake: update SwiftSupport from XCTest Update the swift support CMake rules from XCTest. This adds support for additional features like partial module compilation which improves incremental builds. It allows for executable and library builds. --- cmake/modules/SwiftSupport.cmake | 136 ++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 39 deletions(-) diff --git a/cmake/modules/SwiftSupport.cmake b/cmake/modules/SwiftSupport.cmake index 2a3f4d61a..478f24118 100644 --- a/cmake/modules/SwiftSupport.cmake +++ b/cmake/modules/SwiftSupport.cmake @@ -1,49 +1,55 @@ include(CMakeParseArguments) -function(add_swift_library library) - set(options) +function(add_swift_target target) + set(options LIBRARY) set(single_value_options MODULE_NAME;MODULE_LINK_NAME;MODULE_PATH;MODULE_CACHE_PATH;OUTPUT;TARGET) - set(multiple_value_options SOURCES;SWIFT_FLAGS;CFLAGS;DEPENDS) + set(multiple_value_options CFLAGS;DEPENDS;LINK_FLAGS;SOURCES;SWIFT_FLAGS) - cmake_parse_arguments(ASL "${options}" "${single_value_options}" "${multiple_value_options}" ${ARGN}) + cmake_parse_arguments(AST "${options}" "${single_value_options}" "${multiple_value_options}" ${ARGN}) set(flags ${CMAKE_SWIFT_FLAGS}) + set(link_flags) - list(APPEND flags -emit-library) - - if(ASL_TARGET) - list(APPEND FLAGS -target;${ASL_TARGET}) + if(AST_TARGET) + list(APPEND flags -target;${AST_TARGET}) endif() - if(ASL_MODULE_NAME) - list(APPEND flags -module-name;${ASL_MODULE_NAME}) - endif() - if(ASL_MODULE_LINK_NAME) - list(APPEND flags -module-link-name;${ASL_MODULE_LINK_NAME}) + if(AST_MODULE_NAME) + list(APPEND flags -module-name;${AST_MODULE_NAME}) + else() + list(APPEND flags -module-name;${target}) endif() - if(ASL_MODULE_PATH) - list(APPEND flags -emit-module-path;${ASL_MODULE_PATH}) + if(AST_MODULE_LINK_NAME) + list(APPEND flags -module-link-name;${AST_MODULE_LINK_NAME}) endif() - if(ASL_MODULE_CACHE_PATH) - list(APPEND flags -module-cache-path;${ASL_MODULE_CACHE_PATH}) + if(AST_MODULE_CACHE_PATH) + list(APPEND flags -module-cache-path;${AST_MODULE_CACHE_PATH}) endif() - if(ASL_SWIFT_FLAGS) - foreach(flag ${ASL_SWIFT_FLAGS}) + if(AST_SWIFT_FLAGS) + foreach(flag ${AST_SWIFT_FLAGS}) list(APPEND flags ${flag}) endforeach() endif() - if(ASL_CFLAGS) - foreach(flag ${ASL_CFLAGS}) + if(AST_CFLAGS) + foreach(flag ${AST_CFLAGS}) list(APPEND flags -Xcc;${flag}) endforeach() endif() - - # FIXME: We shouldn't /have/ to build things in a single process. - # - list(APPEND flags -force-single-frontend-invocation) + if(AST_LINK_FLAGS) + foreach(flag ${AST_LINK_FLAGS}) + list(APPEND link_flags ${flag}) + endforeach() + endif() + if(NOT AST_OUTPUT) + if(AST_LIBRARY) + set(AST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${CMAKE_SHARED_LIBRARY_PREFIX}${target}${CMAKE_SHARED_LIBRARY_SUFFIX}) + else() + set(AST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${target}${CMAKE_EXECUTABLE_SUFFIX}) + endif() + endif() set(sources) - foreach(source ${ASL_SOURCES}) + foreach(source ${AST_SOURCES}) get_filename_component(location ${source} PATH) if(IS_ABSOLUTE ${location}) list(APPEND sources ${source}) @@ -52,25 +58,77 @@ function(add_swift_library library) endif() endforeach() - get_filename_component(module_directory ${ASL_MODULE_PATH} DIRECTORY) + set(objs) + set(mods) + set(docs) + set(i 0) + foreach(source ${sources}) + get_filename_component(name ${source} NAME) + + set(obj ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${name}${CMAKE_C_OUTPUT_EXTENSION}) + set(mod ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${name}.swiftmodule) + set(doc ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${name}.swiftdoc) + + set(all_sources ${sources}) + list(INSERT all_sources ${i} -primary-file) + + add_custom_command(OUTPUT + ${obj} + ${mod} + ${doc} + DEPENDS + ${source} + COMMAND + ${CMAKE_SWIFT_COMPILER} -frontend ${flags} -emit-module-path ${mod} -emit-module-doc-path ${doc} -o ${obj} -c ${all_sources}) + + list(APPEND objs ${obj}) + list(APPEND mods ${mod}) + list(APPEND docs ${doc}) + + math(EXPR i "${i}+1") + endforeach() + + if(AST_LIBRARY) + get_filename_component(module_directory ${AST_MODULE_PATH} DIRECTORY) + + set(module ${AST_MODULE_PATH}) + set(documentation ${module_directory}/${AST_MODULE_NAME}.swiftdoc) + + add_custom_command(OUTPUT + ${module} + ${documentation} + DEPENDS + ${mods} + ${docs} + COMMAND + ${CMAKE_SWIFT_COMPILER} -frontend ${flags} -sil-merge-partial-modules -emit-module ${mods} -o ${module} -emit-module-doc-path ${documentation}) + endif() + if(AST_LIBRARY) + set(emit_library -emit-library) + endif() add_custom_command(OUTPUT - ${ASL_OUTPUT} - ${ASL_MODULE_PATH} - ${module_directory}/${ASL_MODULE_NAME}.swiftdoc + ${AST_OUTPUT} DEPENDS - ${ASL_SOURCES} - ${CMAKE_SWIFT_COMPILER} - ${ASL_DEPENDS} + ${objs} COMMAND - ${CMAKE_COMMAND} -E make_directory ${module_directory} + ${CMAKE_SWIFT_COMPILER} ${emit_library} ${link_flags} -o ${AST_OUTPUT} ${objs} COMMAND - ${CMAKE_SWIFT_COMPILER} ${flags} -c ${sources} -o ${ASL_OUTPUT}) - add_custom_target(${library} + ${CMAKE_COMMAND} -E copy ${AST_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_target(${target} + ALL DEPENDS - ${ASL_OUTPUT} - ${ASL_MODULE_PATH} - ${module_directory}/${ASL_MODULE_NAME}.swiftdoc) + ${AST_OUTPUT} + ${module} + ${documentation}) +endfunction() + +function(add_swift_library library) + add_swift_target(${library} LIBRARY ${ARGN}) +endfunction() + +function(add_swift_executable executable) + add_swift_target(${executable} ${ARGN}) endfunction() # Returns the current achitecture name in a variable From 965739e58d3217753c7b2c69b53db803dd9b95c8 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 11 Oct 2018 21:27:22 -0700 Subject: [PATCH 2/4] cmake: support static and shared swift libraries Enhance add_wift_target to support building static libraries. We would always generate shared libraries previously. --- cmake/modules/SwiftSupport.cmake | 68 ++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/cmake/modules/SwiftSupport.cmake b/cmake/modules/SwiftSupport.cmake index 478f24118..92f6f7a02 100644 --- a/cmake/modules/SwiftSupport.cmake +++ b/cmake/modules/SwiftSupport.cmake @@ -2,7 +2,7 @@ include(CMakeParseArguments) function(add_swift_target target) - set(options LIBRARY) + set(options LIBRARY;SHARED;STATIC) set(single_value_options MODULE_NAME;MODULE_LINK_NAME;MODULE_PATH;MODULE_CACHE_PATH;OUTPUT;TARGET) set(multiple_value_options CFLAGS;DEPENDS;LINK_FLAGS;SOURCES;SWIFT_FLAGS) @@ -40,9 +40,28 @@ function(add_swift_target target) list(APPEND link_flags ${flag}) endforeach() endif() + if(AST_LIBRARY) + if(AST_STATIC AND AST_SHARED) + message(SEND_ERROR "add_swift_target asked to create library as STATIC and SHARED") + elseif(AST_STATIC OR NOT BUILD_SHARED_LIBS) + set(library_kind STATIC) + elseif(AST_SHARED OR BUILD_SHARED_LIBS) + set(library_kind SHARED) + endif() + else() + if(AST_STATIC OR AST_SHARED) + message(SEND_ERROR "add_swift_target asked to create executable as STATIC or SHARED") + endif() + endif() if(NOT AST_OUTPUT) if(AST_LIBRARY) - set(AST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${CMAKE_SHARED_LIBRARY_PREFIX}${target}${CMAKE_SHARED_LIBRARY_SUFFIX}) + if(AST_SHARED OR BUILD_SHARED_LIBS) + set(AST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${CMAKE_SHARED_LIBRARY_PREFIX}${target}${CMAKE_SHARED_LIBRARY_SUFFIX}) + else() + # NOTE(compnerd) this is a hack for the computation of the + # basename/dirname below for the static path. + set(AST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${target}) + endif() else() set(AST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${target}.dir/${target}${CMAKE_EXECUTABLE_SUFFIX}) endif() @@ -107,20 +126,37 @@ function(add_swift_target target) if(AST_LIBRARY) set(emit_library -emit-library) endif() - add_custom_command(OUTPUT - ${AST_OUTPUT} - DEPENDS - ${objs} - COMMAND - ${CMAKE_SWIFT_COMPILER} ${emit_library} ${link_flags} -o ${AST_OUTPUT} ${objs} - COMMAND - ${CMAKE_COMMAND} -E copy ${AST_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}) - add_custom_target(${target} - ALL - DEPENDS - ${AST_OUTPUT} - ${module} - ${documentation}) + if(library_kind STREQUAL SHARED) + add_custom_command(OUTPUT + ${AST_OUTPUT} + DEPENDS + ${objs} + COMMAND + ${CMAKE_SWIFT_COMPILER} ${emit_library} ${link_flags} -o ${AST_OUTPUT} ${objs} + COMMAND + ${CMAKE_COMMAND} -E copy ${AST_OUTPUT} ${CMAKE_CURRENT_BINARY_DIR}) + add_custom_target(${target} + ALL + DEPENDS + ${AST_OUTPUT} + ${module} + ${documentation}) + else() + add_library(${target}-static STATIC ${objs}) + get_filename_component(ast_output_bn ${AST_OUTPUT} NAME) + get_filename_component(ast_output_dn ${AST_OUTPUT} DIRECTORY) + set_target_properties(${target}-static + PROPERTIES + LINKER_LANGUAGE C + OUTPUT_DIRECTORY ${ast_output_dn} + OUTPUT_NAME ${ast_output_bn}) + add_custom_target(${target} + ALL + DEPENDS + ${target}-static + ${module} + ${documentation}) + endif() endfunction() function(add_swift_library library) From cbe5c1d049656aacf9ceb515f4334eac97d82a88 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 11 Oct 2018 22:28:56 -0700 Subject: [PATCH 3/4] build: split out the SDK overlay This splits out the SDK overlay component and libdispatch runtime itself. Doing so enables the re-use of libdispatch with and without swift and makes the behaviour similar across Darwin and other platforms. --- src/CMakeLists.txt | 83 ++++++++++++++++++++++++++++---------------- tests/CMakeLists.txt | 16 --------- 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index efe3aed2f..31b5ddad5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,25 +72,60 @@ 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) + 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) + add_swift_library(swiftDispatch + CFLAGS + -fblocks + -fmodule-map-file=${PROJECT_SOURCE_DIR}/dispatch/module.modulemap + DEPENDS + ${PROJECT_SOURCE_DIR}/dispatch/module.modulemap + DispatchStubs + LINK_FLAGS + -lDispatchStubs + -L $ + -ldispatch MODULE_NAME Dispatch MODULE_LINK_NAME - dispatch + swiftDispatch MODULE_PATH ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftmodule - OUTPUT - ${CMAKE_CURRENT_BINARY_DIR}/swiftDispatch.o SOURCES swift/Block.swift swift/Data.swift @@ -101,32 +136,12 @@ if(ENABLE_SWIFT) swift/Source.swift swift/Time.swift swift/Wrapper.swift - TARGET - ${CMAKE_C_COMPILER_TARGET} - CFLAGS - -fblocks - -fmodule-map-file=${PROJECT_SOURCE_DIR}/dispatch/module.modulemap SWIFT_FLAGS -I ${PROJECT_SOURCE_DIR} -I/usr/include ${swift_optimization_flags} - DEPENDS - ${PROJECT_SOURCE_DIR}/dispatch/module.modulemap) - - get_filename_component(swift_toolchain ${CMAKE_SWIFT_COMPILER} DIRECTORY) - get_filename_component(swift_toolchain ${swift_toolchain} DIRECTORY) - set(swift_runtime_libdir ${swift_toolchain}/lib/${swift_dir}/${swift_os}/${swift_arch}) - - target_sources(dispatch - PRIVATE - swift/DispatchStubs.cc - ${CMAKE_CURRENT_BINARY_DIR}/swiftDispatch.o - ${swift_runtime_libdir}/swiftrt.o) - if(CMAKE_BUILD_TYPE MATCHES Debug) - target_link_libraries(dispatch - PRIVATE - swiftSwiftOnoneSupport) - endif() + TARGET + ${CMAKE_C_COMPILER_TARGET}) endif() if(ENABLE_DTRACE) dtrace_usdt_probe(${CMAKE_CURRENT_SOURCE_DIR}/provider.d @@ -231,8 +246,6 @@ add_custom_command(TARGET dispatch POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ .libs COMMENT "Copying libdispatch to .libs") -get_swift_host_arch(SWIFT_HOST_ARCH) - install(TARGETS dispatch DESTINATION @@ -242,6 +255,18 @@ if(ENABLE_SWIFT) ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftmodule ${CMAKE_CURRENT_BINARY_DIR}/swift/Dispatch.swiftdoc DESTINATION - "${INSTALL_TARGET_DIR}/${SWIFT_HOST_ARCH}") + ${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}) + install(FILES + ${swiftDispatch_OUTPUT_FILE} + DESTINATION + ${INSTALL_TARGET_DIR}) endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index eca431cef..453b59a3d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -56,12 +56,6 @@ if(BSD_OVERLAY_FOUND) PRIVATE ${BSD_OVERLAY_LDFLAGS}) endif() -if(ENABLE_SWIFT) - target_link_libraries(bsdtestharness - PRIVATE - swiftCore-${swift_os}-${swift_arch} - swiftSwiftOnoneSupport-${swift_os}-${swift_arch}) -endif() function(add_unit_test name) set(options DISABLED_TEST;NO_BSD_OVERLAY) @@ -83,10 +77,6 @@ function(add_unit_test name) # For testing in swift.org CI system; make deadlines lenient by default # to reduce probability of test failures due to machine load. target_compile_options(${name} PRIVATE -DLENIENT_DEADLINES=1) - target_link_libraries(${name} - PRIVATE - swiftCore-${swift_os}-${swift_arch} - swiftSwiftOnoneSupport-${swift_os}-${swift_arch}) endif() target_include_directories(${name} SYSTEM BEFORE PRIVATE @@ -114,12 +104,6 @@ function(add_unit_test name) PRIVATE ${BSD_OVERLAY_LDFLAGS}) endif() - if(ENABLE_SWIFT) - target_link_libraries(${name} - PRIVATE - swiftCore-${swift_os}-${swift_arch} - swiftSwiftOnoneSupport-${swift_os}-${swift_arch}) - endif() target_link_libraries(${name} PRIVATE bsdtests) add_test(NAME ${name} COMMAND bsdtestharness $) From 3526fabc8fea9a01af2dd521432091ec683a4d57 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 23 Oct 2018 14:53:45 -0700 Subject: [PATCH 4/4] build: correct dependency tracking --- cmake/modules/SwiftSupport.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/modules/SwiftSupport.cmake b/cmake/modules/SwiftSupport.cmake index 92f6f7a02..537e60cb8 100644 --- a/cmake/modules/SwiftSupport.cmake +++ b/cmake/modules/SwiftSupport.cmake @@ -97,6 +97,7 @@ function(add_swift_target target) ${doc} DEPENDS ${source} + ${AST_DEPENDS} COMMAND ${CMAKE_SWIFT_COMPILER} -frontend ${flags} -emit-module-path ${mod} -emit-module-doc-path ${doc} -o ${obj} -c ${all_sources}) @@ -119,6 +120,7 @@ function(add_swift_target target) DEPENDS ${mods} ${docs} + ${AST_DEPENDS} COMMAND ${CMAKE_SWIFT_COMPILER} -frontend ${flags} -sil-merge-partial-modules -emit-module ${mods} -o ${module} -emit-module-doc-path ${documentation}) endif() @@ -131,6 +133,7 @@ function(add_swift_target target) ${AST_OUTPUT} DEPENDS ${objs} + ${AST_DEPENDS} COMMAND ${CMAKE_SWIFT_COMPILER} ${emit_library} ${link_flags} -o ${AST_OUTPUT} ${objs} COMMAND