From 9c9010e5b7506c4bd89c5ef0148e4741b32a1a2c Mon Sep 17 00:00:00 2001 From: Rintaro Ishizaki Date: Sat, 19 Aug 2023 00:18:53 +0000 Subject: [PATCH 01/12] [CMake] Support Macros in Linux For compiling codes required for macro support, we now need swiftc compiler in the build machine. Unlike Darwin OSes, where swiftCore runtime is guaranteed to be present in /usr/lib, Linux doesn't have ABI stability and the stdlib of the build machine is not at the specific location. So the built compiler cannot relies on the shared object in the toolchain. --- CMakeLists.txt | 1 + SwiftCompilerSources/CMakeLists.txt | 8 ++- cmake/modules/AddPureSwift.cmake | 22 ++++++ cmake/modules/AddSwift.cmake | 22 ++++-- cmake/modules/AddSwiftUnittests.cmake | 27 ++++++- cmake/modules/SwiftImplicitImport.cmake | 2 +- cmake/modules/SwiftStripBuilderRpath.cmake | 71 +++++++++++++++++++ lib/CMakeLists.txt | 43 +++++++++-- lib/Macros/CMakeLists.txt | 25 ++++++- lib/SwiftDemangle/CMakeLists.txt | 7 ++ test/lit.cfg | 38 +++++----- .../cmake/modules/AddSwiftSourceKit.cmake | 26 +++---- .../tools/complete-test/CMakeLists.txt | 6 ++ .../tools/sourcekitd-repl/CMakeLists.txt | 6 ++ .../tools/sourcekitd-test/CMakeLists.txt | 6 ++ tools/libStaticMirror/CMakeLists.txt | 6 ++ tools/libSwiftScan/CMakeLists.txt | 29 ++++++-- tools/swift-plugin-server/CMakeLists.txt | 5 ++ unittests/SwiftDemangle/CMakeLists.txt | 2 +- unittests/Threading/CMakeLists.txt | 2 +- unittests/runtime/CMakeLists.txt | 2 +- unittests/runtime/LongTests/CMakeLists.txt | 2 +- utils/build-presets.ini | 3 +- .../products/earlyswiftsyntax.py | 20 ++---- 24 files changed, 304 insertions(+), 77 deletions(-) create mode 100644 cmake/modules/SwiftStripBuilderRpath.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 753ff53570787..b8e072d218c02 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -794,6 +794,7 @@ include(SwiftConfigureSDK) include(SwiftComponents) include(SwiftList) include(AddPureSwift) +include(SwiftStripBuilderRpath) # Configure swift include, install, build components. swift_configure_components() diff --git a/SwiftCompilerSources/CMakeLists.txt b/SwiftCompilerSources/CMakeLists.txt index 4fbd4fca9e514..138d208d9a3a9 100644 --- a/SwiftCompilerSources/CMakeLists.txt +++ b/SwiftCompilerSources/CMakeLists.txt @@ -235,7 +235,7 @@ else() # # step 1: generate a dummy source file, which just includes all headers # defined in include/swift/module.modulemap - file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/HeaderDependencies.cpp" + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/HeaderDependencies.cpp.tmp" " #include \"Basic/BridgedSwiftObject.h\" #include \"Basic/BasicBridging.h\" @@ -251,6 +251,12 @@ else() #include \"Parse/RegexParserBridging.h\" ") + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/HeaderDependencies.cpp" + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${CMAKE_CURRENT_BINARY_DIR}/HeaderDependencies.cpp.tmp" + "${CMAKE_CURRENT_BINARY_DIR}/HeaderDependencies.cpp" + ) # step 2: build a library containing that source file. This library depends on all the included header files. # The swift modules can now depend on that target. diff --git a/cmake/modules/AddPureSwift.cmake b/cmake/modules/AddPureSwift.cmake index 8d26200a551d3..401fdeb4e46bd 100644 --- a/cmake/modules/AddPureSwift.cmake +++ b/cmake/modules/AddPureSwift.cmake @@ -65,6 +65,27 @@ function(_add_host_swift_compile_options name) _add_host_variant_swift_sanitizer_flags(${name}) endfunction() +function(_set_pure_swift_link_flags name relpath_to_lib_dir) + if(SWIFT_HOST_VARIANT_SDK STREQUAL "LINUX") + # Don't add builder's stdlib RPATH automatically, because we want to *de-prioritize* it. + target_compile_options(${name} PRIVATE + $<$:-no-toolchain-stdlib-rpath> + ) + + get_filename_component(swift_bin_dir ${CMAKE_Swift_COMPILER} DIRECTORY) + get_filename_component(swift_dir ${swift_bin_dir} DIRECTORY) + set(host_lib_dir "${swift_dir}/lib/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}") + + set_property(TARGET ${name} + APPEND PROPERTY INSTALL_RPATH + # At runtime, use swiftCore in the current toolchain. + "$ORIGIN/${relpath_to_lib_dir}/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}" + # But before building the stdlib with the tool, use the builder libs. This should be removed in install time. + "${host_lib_dir}") + + endif() +endfunction() + # Add a new "pure" Swift host library. # # "Pure" Swift host libraries can only contain Swift code, and will be built @@ -266,6 +287,7 @@ function(add_pure_swift_host_tool name) # Create the library. add_executable(${name} ${APSHT_SOURCES}) _add_host_swift_compile_options(${name}) + _set_pure_swift_link_flags(${name} "../lib") if(SWIFT_HOST_VARIANT_SDK IN_LIST SWIFT_DARWIN_PLATFORMS) set_property(TARGET ${name} diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake index d4f19d1e2d376..1f0030339034a 100644 --- a/cmake/modules/AddSwift.cmake +++ b/cmake/modules/AddSwift.cmake @@ -548,10 +548,14 @@ function(_add_swift_runtime_link_flags target relpath_to_lib_dir bootstrapping) target_link_libraries(${target} PRIVATE "swiftCore") target_link_directories(${target} PRIVATE ${host_lib_dir}) + + # At runtime, use swiftCore in the current toolchain. + # FIXME: This assumes the ABI hasn't changed since the builder. + set(swift_runtime_rpath "$ORIGIN/${relpath_to_lib_dir}/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}") + if(ASRLF_BOOTSTRAPPING_MODE STREQUAL "HOSTTOOLS") - set(swift_runtime_rpath "${host_lib_dir}") - else() - set(swift_runtime_rpath "$ORIGIN/${relpath_to_lib_dir}/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}") + # But before building the stdlib with the tool, use the builder libs. This should be removed in install time. + list(APPEND swift_runtime_rpath "${host_lib_dir}") endif() elseif(ASRLF_BOOTSTRAPPING_MODE STREQUAL "BOOTSTRAPPING") @@ -576,9 +580,6 @@ function(_add_swift_runtime_link_flags target relpath_to_lib_dir bootstrapping) endif() if(SWIFT_SWIFT_PARSER) - # Make sure we can find the early SwiftSyntax libraries. - target_link_directories(${target} PRIVATE "${SWIFT_PATH_TO_EARLYSWIFTSYNTAX_BUILD_DIR}/lib/swift/host") - # For the "end step" of bootstrapping configurations, we need to be # able to fall back to the SDK directory for libswiftCore et al. if (BOOTSTRAPPING_MODE MATCHES "BOOTSTRAPPING.*") @@ -967,7 +968,14 @@ function(add_swift_host_tool executable) swift_install_in_component(TARGETS ${executable} RUNTIME DESTINATION bin - COMPONENT ${ASHT_SWIFT_COMPONENT}) + COMPONENT ${ASHT_SWIFT_COMPONENT} + ) + + swift_install_strip_builder_rpath( + TARGETS ${executable} + DESTINATION bin + COMPONENT ${ASHT_SWIFT_COMPONENT} + ) swift_is_installing_component(${ASHT_SWIFT_COMPONENT} is_installing) endif() diff --git a/cmake/modules/AddSwiftUnittests.cmake b/cmake/modules/AddSwiftUnittests.cmake index a4573981c225c..45acb9bf10698 100644 --- a/cmake/modules/AddSwiftUnittests.cmake +++ b/cmake/modules/AddSwiftUnittests.cmake @@ -5,10 +5,32 @@ add_custom_target(SwiftUnitTests) set_target_properties(SwiftUnitTests PROPERTIES FOLDER "Tests") +# Add a new Swift unit test executable. +# +# Usage: +# add_swift_unittest(name +# [IS_TARGET_TEST] +# source1 [source2 source3 ...]) +# +# name +# Name of the test (e.g., SwiftASTTest). +# +# IS_TARGET_TEST +# Indicates this is a test for target libraries. Not host library. +# This avoids linking with toolchains stdlib. +# +# source1 ... +# Sources to add into this executable. function(add_swift_unittest test_dirname) + cmake_parse_arguments(ASU + "IS_TARGET_TEST" + "" + "" + ${ARGN}) + # *NOTE* Even though "add_unittest" does not have llvm in its name, it is a # function defined by AddLLVM.cmake. - add_unittest(SwiftUnitTests ${test_dirname} ${ARGN}) + add_unittest(SwiftUnitTests ${test_dirname} ${ASU_UNPARSED_ARGUMENTS}) set_target_properties(${test_dirname} PROPERTIES LINKER_LANGUAGE CXX) @@ -89,7 +111,8 @@ function(add_swift_unittest test_dirname) endif() endif() - if (SWIFT_SWIFT_PARSER) + if (SWIFT_SWIFT_PARSER AND NOT ASU_IS_TARGET_TEST) + # Link to stdlib the compiler uses. _add_swift_runtime_link_flags(${test_dirname} "../../lib" "") set_property(TARGET ${test_dirname} PROPERTY BUILD_WITH_INSTALL_RPATH OFF) endif() diff --git a/cmake/modules/SwiftImplicitImport.cmake b/cmake/modules/SwiftImplicitImport.cmake index 50c5e5415ff81..3c79357f01883 100644 --- a/cmake/modules/SwiftImplicitImport.cmake +++ b/cmake/modules/SwiftImplicitImport.cmake @@ -6,7 +6,7 @@ function(swift_supports_implicit_module module_name out_var) "${CMAKE_Swift_COMPILER}" -Xfrontend -disable-implicit-${module_name}-module-import -Xfrontend -parse-stdlib - -c - -o /dev/null + -parse - INPUT_FILE "${CMAKE_BINARY_DIR}/tmp/empty-check-${module_name}.swift" OUTPUT_QUIET ERROR_QUIET diff --git a/cmake/modules/SwiftStripBuilderRpath.cmake b/cmake/modules/SwiftStripBuilderRpath.cmake new file mode 100644 index 0000000000000..8df406b0388df --- /dev/null +++ b/cmake/modules/SwiftStripBuilderRpath.cmake @@ -0,0 +1,71 @@ +set(SWIFT_SET_RPATH_SCRIPT_FILE "${CMAKE_CURRENT_LIST_FILE}") + +function(swift_get_set_rpath_script_file out_var) + set(${out_var} "${SWIFT_SET_RPATH_SCRIPT_FILE}" PARENT_SCOPE) +endfunction() + +# Actual RPATH_SET operation to the file. +function(_swift_set_rpath_impl file new_rpath) + # NOTE: RPATH_SET is not documented, and works only for ELF and XCOFF. + file(RPATH_SET FILE "${file}" NEW_RPATH "${new_rpath}") +endfunction() + +# For 'install(SCRIPT