Skip to content

Commit 809ce72

Browse files
committed
libswift: build support for the initial libswift
* add the (still empty) libswift package * add build support for libswift in CMake * add libswift to swift-frontend and sil-opt The build can be controlled with the LIBSWIFT_BUILD_MODE cmake variable: by default it’s “DISABLE”, which means that libswift is not built. If it’s “HOSTTOOLS”, libswift is built with a pre-installed toolchain on the host system.
1 parent dddbf35 commit 809ce72

File tree

19 files changed

+406
-20
lines changed

19 files changed

+406
-20
lines changed

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ set(SWIFT_TOOLS_ENABLE_LTO OFF CACHE STRING "Build Swift tools with LTO. One
191191
option only affects the tools that run on the host (the compiler), and has
192192
no effect on the target libraries (the standard library and the runtime).")
193193

194+
option(SWIFT_TOOLS_ENABLE_LIBSWIFT
195+
"Enable building libswift and linking libswift into the compiler itself."
196+
FALSE)
197+
194198
# The following only works with the Ninja generator in CMake >= 3.0.
195199
set(SWIFT_PARALLEL_LINK_JOBS "" CACHE STRING
196200
"Define the maximum number of linker jobs for swift.")
@@ -891,6 +895,7 @@ if(SWIFT_INCLUDE_TOOLS)
891895
message(STATUS " Build type: ${CMAKE_BUILD_TYPE}")
892896
message(STATUS " Assertions: ${LLVM_ENABLE_ASSERTIONS}")
893897
message(STATUS " LTO: ${SWIFT_TOOLS_ENABLE_LTO}")
898+
message(STATUS " libswift: ${SWIFT_TOOLS_ENABLE_LIBSWIFT}")
894899
message(STATUS "")
895900
else()
896901
message(STATUS "Not building host Swift tools")
@@ -1034,6 +1039,11 @@ add_subdirectory(include)
10341039
if(SWIFT_INCLUDE_TOOLS)
10351040
add_subdirectory(lib)
10361041

1042+
# "libswift" must come before "tools".
1043+
# It adds libswift module names to the global property "libswift_modules"
1044+
# which is used in add_swift_host_tool for the lldb workaround.
1045+
add_subdirectory(libswift)
1046+
10371047
# Always include this after including stdlib/!
10381048
# Refer to the large comment above the add_subdirectory(stdlib) call.
10391049
# https://bugs.swift.org/browse/SR-5975

cmake/modules/AddSwift.cmake

Lines changed: 150 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,121 @@ function(add_swift_host_library name)
607607
endif()
608608
endfunction()
609609
610+
# Add a module of libswift
611+
#
612+
# Creates a target to compile a module which is part of libswift.
613+
# Adds the module name to the global property "libswift_modules".
614+
#
615+
# This is a temporary workaround until it's possible to compile libswift with
616+
# cmake's builtin swift support.
617+
function(add_libswift_module module)
618+
cmake_parse_arguments(ALSM
619+
""
620+
"DEPENDS"
621+
""
622+
${ARGN})
623+
set(sources ${ALSM_UNPARSED_ARGUMENTS})
624+
list(TRANSFORM sources PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
625+
626+
set(target_name "LibSwift${module}")
627+
628+
# Add a target which depends on the actual compilation target, which
629+
# will be created in add_libswift.
630+
# This target is mainly used to add properties, like the list of source files.
631+
add_custom_target(
632+
${target_name}
633+
SOURCES ${sources}
634+
COMMENT "libswift module ${module}")
635+
636+
set_property(TARGET ${target_name} PROPERTY "module_name" ${module})
637+
set_property(TARGET ${target_name} PROPERTY "module_depends" ${ALSM_DEPENDS})
638+
639+
get_property(modules GLOBAL PROPERTY "libswift_modules")
640+
set_property(GLOBAL PROPERTY "libswift_modules" ${modules} ${module})
641+
endfunction()
642+
643+
# Add source files to a libswift module.
644+
#
645+
# This is a temporary workaround until it's possible to compile libswift with
646+
# cmake's builtin swift support.
647+
function(libswift_sources module)
648+
cmake_parse_arguments(LSS
649+
""
650+
""
651+
""
652+
${ARGN})
653+
set(sources ${LSS_UNPARSED_ARGUMENTS})
654+
list(TRANSFORM sources PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
655+
656+
set(target_name "LibSwift${module}")
657+
set_property(TARGET "LibSwift${module}" APPEND PROPERTY SOURCES ${sources})
658+
endfunction()
659+
660+
# Add the libswift library.
661+
#
662+
# Adds targets to compile all modules of libswift and a target for the
663+
# libswift library itself.
664+
#
665+
# This is a temporary workaround until it's possible to compile libswift with
666+
# cmake's builtin swift support.
667+
function(add_libswift name)
668+
if(CMAKE_BUILD_TYPE STREQUAL Debug)
669+
set(libswift_compile_options "-g")
670+
else()
671+
set(libswift_compile_options "-O" "-cross-module-optimization")
672+
endif()
673+
674+
set(build_dir ${CMAKE_CURRENT_BINARY_DIR})
675+
676+
if(SWIFT_HOST_VARIANT_SDK IN_LIST SWIFT_APPLE_PLATFORMS)
677+
set(deployment_version "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_DEPLOYMENT_VERSION}")
678+
endif()
679+
get_versioned_target_triple(target ${SWIFT_HOST_VARIANT_SDK}
680+
${SWIFT_HOST_VARIANT_ARCH} "${deployment_version}")
681+
682+
get_property(modules GLOBAL PROPERTY "libswift_modules")
683+
foreach(module ${modules})
684+
685+
set(module_target "LibSwift${module}")
686+
get_target_property(module ${module_target} "module_name")
687+
get_target_property(sources ${module_target} SOURCES)
688+
get_target_property(dependencies ${module_target} "module_depends")
689+
if(dependencies)
690+
list(TRANSFORM dependencies PREPEND "LibSwift")
691+
else()
692+
set(dependencies "")
693+
endif()
694+
695+
set(module_obj_file "${build_dir}/${module}.o")
696+
set(module_file "${build_dir}/${module}.swiftmodule")
697+
set_property(TARGET ${module_target} PROPERTY "module_file" "${module_file}")
698+
699+
set(all_obj_files ${all_obj_files} ${module_obj_file})
700+
701+
# Compile the libswift module into an object file
702+
add_custom_command_target(dep_target OUTPUT ${module_obj_file}
703+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
704+
DEPENDS ${sources} ${dependencies}
705+
COMMAND ${CMAKE_Swift_COMPILER} "-c" "-o" ${module_obj_file}
706+
"-sdk" "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_ARCH_${SWIFT_HOST_VARIANT_ARCH}_PATH}"
707+
"-target" ${target}
708+
"-module-name" ${module} "-emit-module"
709+
"-emit-module-path" "${build_dir}/${module}.swiftmodule"
710+
"-parse-as-library" ${sources}
711+
"-wmo" ${libswift_compile_options}
712+
"-I" "${CMAKE_SOURCE_DIR}/include/swift"
713+
"-I" "${build_dir}"
714+
COMMENT "Building libswift module ${module}")
715+
716+
add_dependencies(${module_target} ${dep_target})
717+
718+
endforeach()
719+
720+
# Create a static libswift library containing all module object files.
721+
add_library(${name} STATIC ${all_obj_files})
722+
set_target_properties(${name} PROPERTIES LINKER_LANGUAGE CXX)
723+
endfunction()
724+
610725
macro(add_swift_tool_subdirectory name)
611726
add_llvm_subdirectory(SWIFT TOOL ${name})
612727
endmacro()
@@ -616,7 +731,7 @@ macro(add_swift_lib_subdirectory name)
616731
endmacro()
617732
618733
function(add_swift_host_tool executable)
619-
set(options)
734+
set(options HAS_LIBSWIFT)
620735
set(single_parameter_options SWIFT_COMPONENT)
621736
set(multiple_parameter_options LLVM_LINK_COMPONENTS)
622737
@@ -668,6 +783,24 @@ function(add_swift_host_tool executable)
668783
get_filename_component(TOOLCHAIN_BIN_DIR ${CMAKE_Swift_COMPILER} DIRECTORY)
669784
get_filename_component(TOOLCHAIN_LIB_DIR "${TOOLCHAIN_BIN_DIR}/../lib/swift/macosx" ABSOLUTE)
670785
target_link_directories(${executable} PUBLIC ${TOOLCHAIN_LIB_DIR})
786+
787+
if (ASHT_HAS_LIBSWIFT AND SWIFT_TOOLS_ENABLE_LIBSWIFT)
788+
# Workaround to make lldb happy: we have to explicitly add all libswift modules
789+
# to the linker command line.
790+
set(libswift_ast_path_flags "-Wl")
791+
get_property(modules GLOBAL PROPERTY "libswift_modules")
792+
foreach(module ${modules})
793+
get_target_property(module_file "LibSwift${module}" "module_file")
794+
string(APPEND libswift_ast_path_flags ",-add_ast_path,${module_file}")
795+
endforeach()
796+
797+
set_property(TARGET ${executable} APPEND_STRING PROPERTY
798+
LINK_FLAGS ${libswift_ast_path_flags})
799+
800+
# Workaround for a linker crash related to autolinking: rdar://77839981
801+
set_property(TARGET ${executable} APPEND_STRING PROPERTY
802+
LINK_FLAGS " -lobjc ")
803+
endif()
671804
endif()
672805
673806
# Lists of rpaths that we are going to add to our executables.
@@ -687,6 +820,22 @@ function(add_swift_host_tool executable)
687820
set_target_properties(${executable} PROPERTIES
688821
BUILD_WITH_INSTALL_RPATH YES
689822
INSTALL_RPATH "${RPATH_LIST}")
823+
824+
elseif(SWIFT_HOST_VARIANT_SDK STREQUAL "LINUX")
825+
if (ASHT_HAS_LIBSWIFT AND SWIFT_TOOLS_ENABLE_LIBSWIFT)
826+
# At build time and and run time, link against the swift libraries in the
827+
# installed host toolchain.
828+
get_filename_component(swift_bin_dir ${CMAKE_Swift_COMPILER} DIRECTORY)
829+
get_filename_component(swift_dir ${swift_bin_dir} DIRECTORY)
830+
set(host_lib_dir "${swift_dir}/lib/swift/linux")
831+
832+
target_link_libraries(${executable} PRIVATE "swiftCore")
833+
834+
target_link_directories(${executable} PRIVATE ${host_lib_dir})
835+
set_target_properties(${executable} PROPERTIES
836+
BUILD_WITH_INSTALL_RPATH YES
837+
INSTALL_RPATH "${host_lib_dir}")
838+
endif()
690839
endif()
691840
692841
llvm_update_compile_flags(${executable})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===--- InitializeLibSwift.h -----------------------------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_BASIC_INITIALIZELIBSWIFT_H
14+
#define SWIFT_BASIC_INITIALIZELIBSWIFT_H
15+
16+
#ifdef __cplusplus
17+
extern "C" {
18+
#endif
19+
20+
void initializeLibSwift();
21+
22+
#ifdef __cplusplus
23+
}
24+
#endif
25+
26+
#endif // SWIFT_BASIC_INITIALIZELIBSWIFT_H

lib/Immediate/Immediate.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -237,26 +237,42 @@ int swift::RunImmediately(CompilerInstance &CI,
237237
//
238238
// This must be done here, before any library loading has been done, to avoid
239239
// racing with the static initializers in user code.
240+
// Setup interpreted process arguments.
241+
using ArgOverride = void (*)(const char **, int);
242+
#if defined(_WIN32)
240243
auto stdlib = loadSwiftRuntime(Context.SearchPathOpts.RuntimeLibraryPaths);
241244
if (!stdlib) {
242245
CI.getDiags().diagnose(SourceLoc(),
243246
diag::error_immediate_mode_missing_stdlib);
244247
return -1;
245248
}
246-
247-
// Setup interpreted process arguments.
248-
using ArgOverride = void (*)(const char **, int);
249-
#if defined(_WIN32)
250249
auto module = static_cast<HMODULE>(stdlib);
251250
auto emplaceProcessArgs = reinterpret_cast<ArgOverride>(
252251
GetProcAddress(module, "_swift_stdlib_overrideUnsafeArgvArgc"));
253252
if (emplaceProcessArgs == nullptr)
254253
return -1;
255254
#else
255+
// In case the compiler is built with libswift, it already has the stdlib
256+
// linked to. First try to lookup the symbol with the standard library
257+
// resolving.
256258
auto emplaceProcessArgs
257-
= (ArgOverride)dlsym(stdlib, "_swift_stdlib_overrideUnsafeArgvArgc");
258-
if (dlerror())
259-
return -1;
259+
= (ArgOverride)dlsym(RTLD_DEFAULT, "_swift_stdlib_overrideUnsafeArgvArgc");
260+
261+
if (dlerror()) {
262+
// If this does not work (= not build with libswift), we have to explicitly
263+
// load the stdlib.
264+
auto stdlib = loadSwiftRuntime(Context.SearchPathOpts.RuntimeLibraryPaths);
265+
if (!stdlib) {
266+
CI.getDiags().diagnose(SourceLoc(),
267+
diag::error_immediate_mode_missing_stdlib);
268+
return -1;
269+
}
270+
dlerror();
271+
emplaceProcessArgs
272+
= (ArgOverride)dlsym(stdlib, "_swift_stdlib_overrideUnsafeArgvArgc");
273+
if (dlerror())
274+
return -1;
275+
}
260276
#endif
261277

262278
SmallVector<const char *, 32> argBuf;

libswift/CMakeLists.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# This source file is part of the Swift.org open source project
2+
#
3+
# Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
4+
# Licensed under Apache License v2.0 with Runtime Library Exception
5+
#
6+
# See http://swift.org/LICENSE.txt for license information
7+
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
8+
9+
if (NOT SWIFT_TOOLS_ENABLE_LIBSWIFT)
10+
# A dummy libswift if libswift is disabled
11+
add_swift_host_library(libswift OBJECT LibSwiftStubs.cpp)
12+
else()
13+
project(LibSwift LANGUAGES C CXX Swift)
14+
15+
if (NOT CMAKE_Swift_COMPILER)
16+
message(FATAL_ERROR "Need a swift toolchain for building libswift")
17+
endif()
18+
19+
add_subdirectory(Sources)
20+
21+
add_libswift("libswift")
22+
endif()
23+

libswift/LibSwiftStubs.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===--- LibSwiftStubs.cpp ------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
extern "C" {
14+
15+
void initializeLibSwift();
16+
17+
}
18+
19+
void initializeLibSwift() {}
20+

libswift/Package.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// swift-tools-version:5.3
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "libswift",
7+
platforms: [
8+
.macOS("10.9"),
9+
],
10+
products: [
11+
.library(
12+
name: "Swift",
13+
type: .static,
14+
targets: ["SIL", "Optimizer"]),
15+
],
16+
dependencies: [
17+
],
18+
// Note that all modules must be added to LIBSWIFT_MODULES in the top-level
19+
// CMakeLists.txt file to get debugging working.
20+
targets: [
21+
.target(
22+
name: "SIL",
23+
dependencies: [],
24+
swiftSettings: [SwiftSetting.unsafeFlags([
25+
"-I", "../include/swift",
26+
"-cross-module-optimization"
27+
])]),
28+
.target(
29+
name: "Optimizer",
30+
dependencies: ["SIL"],
31+
swiftSettings: [SwiftSetting.unsafeFlags([
32+
"-I", "../include/swift",
33+
"-cross-module-optimization"
34+
])]),
35+
]
36+
)

libswift/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Swift implemented in Swift
2+
3+
_Libswift_ is the part of the Swift compiler, which is implemented in Swift.
4+
5+
With _libswift_ it is possible to add SIL optimization passes written in Swift. It allows to gradually migrate the SIL optimizer from C++ to Swift.
6+
7+
## Building
8+
9+
_Libswift_ is a static library and it is built as part of the swift compiler using build-script and CMake.
10+
11+
To enable _libswift_, add the build-script option `--libswift`.
12+
13+
In this early stage of development _libswift_ is disabled by default. Right now _libswift_ does not contain any optimizations or features which are not available in the existing optimizer. Therefore a compiler with disabled _libswift_ still behaves as a compiler with enabled _libswift_. This will change soon.
14+
15+
When _libswift_ is enabled, it is built with a Swift toolchain (5.3 or newer), which must be installed on the host system. The `swiftc` compiler driver is expected to be in the command search path.
16+
17+
Currently the `swift-frontend` and `sil-opt` tools use _libswift_. Tools, which don't use any optimization passes from _libswift_ don't need to link _libswift_. For example, all tools, which compile Swift source code, but don't optimize it, like SourceKit or lldb, don't need to link _libswift_. As long as `initializeLibSwift()` is not called there is no dependency on _libswift_.
18+
19+
This also means that currently it is not possible to implement mandatory passes in _libswift_, because this would break tools which compile Swift code but don't use _libswift_. When we want to implement mandatory passes in _libswift_ in the future, we'll need to link _libswift_ to all those tools.
20+
21+

0 commit comments

Comments
 (0)