diff --git a/CMakeLists.txt b/CMakeLists.txt index 8129705..f07181f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,11 +10,35 @@ ##===----------------------------------------------------------------------===## cmake_minimum_required(VERSION 3.26...3.29) -project(Subprocess LANGUAGES C Swift) -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") -add_compile_options("$<$:SHELL:-package-name ${PROJECT_NAME}>") +set(CMAKE_C_VISIBILITY_PRESET "hidden") +project(Subprocess + LANGUAGES C Swift) + +list(APPEND CMAKE_MODULE_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + +include(EmitSwiftInterface) +include(GNUInstallDirs) include(InstallExternalDependencies) +include(PlatformInfo) +include(InstallSwiftInterface) + +option(${PROJECT_NAME}_INSTALL_NESTED_SUBDIR "Install libraries under a platform and architecture subdirectory" ON) +set(${PROJECT_NAME}_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}/swift$<$>:_static>$<$:/${${PROJECT_NAME}_PLATFORM_SUBDIR}/${${PROJECT_NAME}_ARCH_SUBDIR}>") +set(${PROJECT_NAME}_INSTALL_SWIFTMODULEDIR "${CMAKE_INSTALL_LIBDIR}/swift$<$>:_static>$<$:/${${PROJECT_NAME}_PLATFORM_SUBDIR}>") + +option(${PROJECT_NAME}_ENABLE_LIBRARY_EVOLUTION "Generate ABI resilient runtime libraries" NO) +option(${PROJECT_NAME}_ENABLE_PRESPECIALIZATION "Enable generic metadata prespecialization" NO) + +add_compile_options( + "$<$:SHELL:-package-name ${PROJECT_NAME}>" + "$<$,$>:-enable-library-evolution>" + "$<$,$>:SHELL:-Xfrontend -prespecialize-generic-metadata>") add_subdirectory(Sources) + +export(EXPORT SwiftSubprocessTargets + FILE "cmake/SwiftSubprocess/SwiftSubprocessTargets.cmake" + NAMESPACE "SwiftSubprocess::") diff --git a/Sources/Subprocess/CMakeLists.txt b/Sources/Subprocess/CMakeLists.txt index 1142445..dea6cd6 100644 --- a/Sources/Subprocess/CMakeLists.txt +++ b/Sources/Subprocess/CMakeLists.txt @@ -46,3 +46,11 @@ target_link_libraries(Subprocess PUBLIC _SubprocessCShims) target_link_libraries(Subprocess PRIVATE SwiftSystem::SystemPackage) + +install(TARGETS Subprocess + EXPORT SwiftSubprocessTargets + ARCHIVE DESTINATION "${${PROJECT_NAME}_INSTALL_LIBDIR}" + LIBRARY DESTINATION "${${PROJECT_NAME}_INSTALL_LIBDIR}" + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") +emit_swift_interface(Subprocess) +install_swift_interface(Subprocess) diff --git a/Sources/_SubprocessCShims/CMakeLists.txt b/Sources/_SubprocessCShims/CMakeLists.txt index 131bc8e..4c152ee 100644 --- a/Sources/_SubprocessCShims/CMakeLists.txt +++ b/Sources/_SubprocessCShims/CMakeLists.txt @@ -13,3 +13,6 @@ add_library(_SubprocessCShims STATIC process_shims.c) target_include_directories(_SubprocessCShims PUBLIC include) + +install(TARGETS _SubprocessCShims + EXPORT SwiftSubprocessTargets) diff --git a/cmake/modules/EmitSwiftInterface.cmake b/cmake/modules/EmitSwiftInterface.cmake new file mode 100644 index 0000000..7f4f489 --- /dev/null +++ b/cmake/modules/EmitSwiftInterface.cmake @@ -0,0 +1,60 @@ +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift.org open source project +## +## Copyright (c) 2025 Apple Inc. and the Swift project authors +## Licensed under Apache License v2.0 with Runtime Library Exception +## +## See https://swift.org/LICENSE.txt for license information +## +##===----------------------------------------------------------------------===## + +function(emit_swift_interface target) + # Generate the target-variant binary swift module when performing zippered + # build + # + # Clean this up once CMake has nested swiftmodules in the build directory: + # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/10664 + # https://cmake.org/cmake/help/git-stage/policy/CMP0195.html + + # We can't expand the Swift_MODULE_NAME target property in a generator + # expression or it will fail saying that the target doesn't exist. + get_target_property(module_name ${target} Swift_MODULE_NAME) + if(NOT module_name) + set(module_name ${target}) + endif() + + # Account for an existing swiftmodule file generated with the previous logic + if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule" + AND NOT IS_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule") + message(STATUS "Removing regular file ${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule to support nested swiftmodule generation") + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule") + endif() + + target_compile_options(${target} PRIVATE + "$<$:SHELL:-emit-module-path ${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule/${${PROJECT_NAME}_MODULE_TRIPLE}.swiftmodule>") + if(${PROJECT_NAME}_VARIANT_MODULE_TRIPLE) + target_compile_options(${target} PRIVATE + "$<$:SHELL:-emit-variant-module-path ${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule/${${PROJECT_NAME}_VARIANT_MODULE_TRIPLE}.swiftmodule>") + endif() + add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule/${${PROJECT_NAME}_MODULE_TRIPLE}.swiftmodule" + DEPENDS ${target}) + target_sources(${target} + INTERFACE + $) + + # Generate textual swift interfaces is library-evolution is enabled + if(${PROJECT_NAME}_ENABLE_LIBRARY_EVOLUTION) + target_compile_options(${target} PRIVATE + $<$:-emit-module-interface-path$${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule/${${PROJECT_NAME}_MODULE_TRIPLE}.swiftinterface> + $<$:-emit-private-module-interface-path$${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule/${${PROJECT_NAME}_MODULE_TRIPLE}.private.swiftinterface>) + if(${PROJECT_NAME}_VARIANT_MODULE_TRIPLE) + target_compile_options(${target} PRIVATE + "$<$:SHELL:-emit-variant-module-interface-path ${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule/${${PROJECT_NAME}_VARIANT_MODULE_TRIPLE}.swiftinterface>" + "$<$:SHELL:-emit-variant-private-module-interface-path ${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule/${${PROJECT_NAME}_VARIANT_MODULE_TRIPLE}.private.swiftinterface>") + endif() + target_compile_options(${target} PRIVATE + $<$:-library-level$api> + $<$:-Xfrontend$-require-explicit-availability=ignore>) + endif() +endfunction() diff --git a/cmake/modules/InstallSwiftInterface.cmake b/cmake/modules/InstallSwiftInterface.cmake new file mode 100644 index 0000000..73b18b4 --- /dev/null +++ b/cmake/modules/InstallSwiftInterface.cmake @@ -0,0 +1,23 @@ +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift.org open source project +## +## Copyright (c) 2025 Apple Inc. and the Swift project authors +## Licensed under Apache License v2.0 with Runtime Library Exception +## +## See https://swift.org/LICENSE.txt for license information +## +##===----------------------------------------------------------------------===## + +# Install the generated swift interface files for the target. +function(install_swift_interface target) + # Swiftmodules are already in the directory structure + get_target_property(module_name ${target} Swift_MODULE_NAME) + if(NOT module_name) + set(module_name ${target}) + endif() + + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${module_name}.swiftmodule" + DESTINATION "${${PROJECT_NAME}_INSTALL_SWIFTMODULEDIR}" + COMPONENT SwiftSubprocess_development) +endfunction() diff --git a/cmake/modules/PlatformInfo.cmake b/cmake/modules/PlatformInfo.cmake new file mode 100644 index 0000000..6680a63 --- /dev/null +++ b/cmake/modules/PlatformInfo.cmake @@ -0,0 +1,43 @@ +##===----------------------------------------------------------------------===## +## +## This source file is part of the Swift.org open source project +## +## Copyright (c) 2025 Apple Inc. and the Swift project authors +## Licensed under Apache License v2.0 with Runtime Library Exception +## +## See https://swift.org/LICENSE.txt for license information +## +##===----------------------------------------------------------------------===## + +# TODO: This logic should migrate to CMake once CMake supports installing swiftmodules +set(module_triple_command "${CMAKE_Swift_COMPILER}" -print-target-info) +if(CMAKE_Swift_COMPILER_TARGET) + list(APPEND module_triple_command -target ${CMAKE_Swift_COMPILER_TARGET}) +endif() +execute_process(COMMAND ${module_triple_command} OUTPUT_VARIABLE target_info_json) +message(CONFIGURE_LOG "Swift target info: ${module_triple_command}\n" +"${target_info_json}") + +if(NOT ${PROJECT_NAME}_MODULE_TRIPLE) + string(JSON module_triple GET "${target_info_json}" "target" "moduleTriple") + set(${PROJECT_NAME}_MODULE_TRIPLE "${module_triple}" CACHE STRING "Triple used for installed swift{doc,module,interface} files") + mark_as_advanced(${PROJECT_NAME}_MODULE_TRIPLE) + + message(CONFIGURE_LOG "Swift module triple: ${module_triple}") +endif() + +if(NOT ${PROJECT_NAME}_PLATFORM_SUBDIR) + string(JSON platform GET "${target_info_json}" "target" "platform") + set(${PROJECT_NAME}_PLATFORM_SUBDIR "${platform}" CACHE STRING "Platform name used for installed swift{doc,module,interface} files") + mark_as_advanced(${PROJECT_NAME}_PLATFORM_SUBDIR) + + message(CONFIGURE_LOG "Swift platform: ${platform}") +endif() + +if(NOT ${PROJECT_NAME}_ARCH_SUBDIR) + string(JSON arch GET "${target_info_json}" "target" "arch") + set(${PROJECT_NAME}_ARCH_SUBDIR "${arch}" CACHE STRING "Architecture used for setting the architecture subdirectory") + mark_as_advanced(${PROJECT_NAME}_ARCH_SUBDIR) + + message(CONFIGURE_LOG "Swift Arch: ${arch}") +endif()